Browse code

vendor swarmkit 970b45afa1c9da9ed4b9c793669cedbb05ad3833

Signed-off-by: Dong Chen <dongluo.chen@docker.com>

Dong Chen authored on 2017/03/29 03:51:33
Showing 62 changed files
... ...
@@ -105,7 +105,7 @@ github.com/docker/containerd 422e31ce907fd9c3833a38d7b8fdd023e5a76e73
105 105
 github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4
106 106
 
107 107
 # cluster
108
-github.com/docker/swarmkit 9fdea50c14492b6e1f472813849794d36bfef217
108
+github.com/docker/swarmkit 970b45afa1c9da9ed4b9c793669cedbb05ad3833
109 109
 github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
110 110
 github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2
111 111
 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
... ...
@@ -195,6 +195,7 @@ type ListTasksRequest_Filters struct {
195 195
 	DesiredStates []TaskState       `protobuf:"varint,6,rep,packed,name=desired_states,json=desiredStates,enum=docker.swarmkit.v1.TaskState" json:"desired_states,omitempty"`
196 196
 	// NamePrefixes matches all objects with the given prefixes
197 197
 	NamePrefixes []string `protobuf:"bytes,7,rep,name=name_prefixes,json=namePrefixes" json:"name_prefixes,omitempty"`
198
+	Runtimes     []string `protobuf:"bytes,9,rep,name=runtimes" json:"runtimes,omitempty"`
198 199
 	// UpToDate matches tasks that are consistent with the current
199 200
 	// service definition.
200 201
 	// Note: this is intended for internal status reporting rather
... ...
@@ -299,6 +300,7 @@ type ListServicesRequest_Filters struct {
299 299
 	Labels     map[string]string `protobuf:"bytes,3,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
300 300
 	// NamePrefixes matches all objects with the given prefixes
301 301
 	NamePrefixes []string `protobuf:"bytes,4,rep,name=name_prefixes,json=namePrefixes" json:"name_prefixes,omitempty"`
302
+	Runtimes     []string `protobuf:"bytes,5,rep,name=runtimes" json:"runtimes,omitempty"`
302 303
 }
303 304
 
304 305
 func (m *ListServicesRequest_Filters) Reset()      { *m = ListServicesRequest_Filters{} }
... ...
@@ -1175,6 +1177,11 @@ func (m *ListTasksRequest_Filters) CopyFrom(src interface{}) {
1175 1175
 		copy(m.NamePrefixes, o.NamePrefixes)
1176 1176
 	}
1177 1177
 
1178
+	if o.Runtimes != nil {
1179
+		m.Runtimes = make([]string, len(o.Runtimes))
1180
+		copy(m.Runtimes, o.Runtimes)
1181
+	}
1182
+
1178 1183
 }
1179 1184
 
1180 1185
 func (m *ListTasksResponse) Copy() *ListTasksResponse {
... ...
@@ -1393,6 +1400,11 @@ func (m *ListServicesRequest_Filters) CopyFrom(src interface{}) {
1393 1393
 		copy(m.NamePrefixes, o.NamePrefixes)
1394 1394
 	}
1395 1395
 
1396
+	if o.Runtimes != nil {
1397
+		m.Runtimes = make([]string, len(o.Runtimes))
1398
+		copy(m.Runtimes, o.Runtimes)
1399
+	}
1400
+
1396 1401
 }
1397 1402
 
1398 1403
 func (m *ListServicesResponse) Copy() *ListServicesResponse {
... ...
@@ -3467,6 +3479,21 @@ func (m *ListTasksRequest_Filters) MarshalTo(dAtA []byte) (int, error) {
3467 3467
 		}
3468 3468
 		i++
3469 3469
 	}
3470
+	if len(m.Runtimes) > 0 {
3471
+		for _, s := range m.Runtimes {
3472
+			dAtA[i] = 0x4a
3473
+			i++
3474
+			l = len(s)
3475
+			for l >= 1<<7 {
3476
+				dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
3477
+				l >>= 7
3478
+				i++
3479
+			}
3480
+			dAtA[i] = uint8(l)
3481
+			i++
3482
+			i += copy(dAtA[i:], s)
3483
+		}
3484
+	}
3470 3485
 	return i, nil
3471 3486
 }
3472 3487
 
... ...
@@ -3832,6 +3859,21 @@ func (m *ListServicesRequest_Filters) MarshalTo(dAtA []byte) (int, error) {
3832 3832
 			i += copy(dAtA[i:], s)
3833 3833
 		}
3834 3834
 	}
3835
+	if len(m.Runtimes) > 0 {
3836
+		for _, s := range m.Runtimes {
3837
+			dAtA[i] = 0x2a
3838
+			i++
3839
+			l = len(s)
3840
+			for l >= 1<<7 {
3841
+				dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
3842
+				l >>= 7
3843
+				i++
3844
+			}
3845
+			dAtA[i] = uint8(l)
3846
+			i++
3847
+			i += copy(dAtA[i:], s)
3848
+		}
3849
+	}
3835 3850
 	return i, nil
3836 3851
 }
3837 3852
 
... ...
@@ -6015,6 +6057,12 @@ func (m *ListTasksRequest_Filters) Size() (n int) {
6015 6015
 	if m.UpToDate {
6016 6016
 		n += 2
6017 6017
 	}
6018
+	if len(m.Runtimes) > 0 {
6019
+		for _, s := range m.Runtimes {
6020
+			l = len(s)
6021
+			n += 1 + l + sovControl(uint64(l))
6022
+		}
6023
+	}
6018 6024
 	return n
6019 6025
 }
6020 6026
 
... ...
@@ -6156,6 +6204,12 @@ func (m *ListServicesRequest_Filters) Size() (n int) {
6156 6156
 			n += 1 + l + sovControl(uint64(l))
6157 6157
 		}
6158 6158
 	}
6159
+	if len(m.Runtimes) > 0 {
6160
+		for _, s := range m.Runtimes {
6161
+			l = len(s)
6162
+			n += 1 + l + sovControl(uint64(l))
6163
+		}
6164
+	}
6159 6165
 	return n
6160 6166
 }
6161 6167
 
... ...
@@ -6738,6 +6792,7 @@ func (this *ListTasksRequest_Filters) String() string {
6738 6738
 		`DesiredStates:` + fmt.Sprintf("%v", this.DesiredStates) + `,`,
6739 6739
 		`NamePrefixes:` + fmt.Sprintf("%v", this.NamePrefixes) + `,`,
6740 6740
 		`UpToDate:` + fmt.Sprintf("%v", this.UpToDate) + `,`,
6741
+		`Runtimes:` + fmt.Sprintf("%v", this.Runtimes) + `,`,
6741 6742
 		`}`,
6742 6743
 	}, "")
6743 6744
 	return s
... ...
@@ -6863,6 +6918,7 @@ func (this *ListServicesRequest_Filters) String() string {
6863 6863
 		`IDPrefixes:` + fmt.Sprintf("%v", this.IDPrefixes) + `,`,
6864 6864
 		`Labels:` + mapStringForLabels + `,`,
6865 6865
 		`NamePrefixes:` + fmt.Sprintf("%v", this.NamePrefixes) + `,`,
6866
+		`Runtimes:` + fmt.Sprintf("%v", this.Runtimes) + `,`,
6866 6867
 		`}`,
6867 6868
 	}, "")
6868 6869
 	return s
... ...
@@ -9037,6 +9093,35 @@ func (m *ListTasksRequest_Filters) Unmarshal(dAtA []byte) error {
9037 9037
 				}
9038 9038
 			}
9039 9039
 			m.UpToDate = bool(v != 0)
9040
+		case 9:
9041
+			if wireType != 2 {
9042
+				return fmt.Errorf("proto: wrong wireType = %d for field Runtimes", wireType)
9043
+			}
9044
+			var stringLen uint64
9045
+			for shift := uint(0); ; shift += 7 {
9046
+				if shift >= 64 {
9047
+					return ErrIntOverflowControl
9048
+				}
9049
+				if iNdEx >= l {
9050
+					return io.ErrUnexpectedEOF
9051
+				}
9052
+				b := dAtA[iNdEx]
9053
+				iNdEx++
9054
+				stringLen |= (uint64(b) & 0x7F) << shift
9055
+				if b < 0x80 {
9056
+					break
9057
+				}
9058
+			}
9059
+			intStringLen := int(stringLen)
9060
+			if intStringLen < 0 {
9061
+				return ErrInvalidLengthControl
9062
+			}
9063
+			postIndex := iNdEx + intStringLen
9064
+			if postIndex > l {
9065
+				return io.ErrUnexpectedEOF
9066
+			}
9067
+			m.Runtimes = append(m.Runtimes, string(dAtA[iNdEx:postIndex]))
9068
+			iNdEx = postIndex
9040 9069
 		default:
9041 9070
 			iNdEx = preIndex
9042 9071
 			skippy, err := skipControl(dAtA[iNdEx:])
... ...
@@ -10158,6 +10243,35 @@ func (m *ListServicesRequest_Filters) Unmarshal(dAtA []byte) error {
10158 10158
 			}
10159 10159
 			m.NamePrefixes = append(m.NamePrefixes, string(dAtA[iNdEx:postIndex]))
10160 10160
 			iNdEx = postIndex
10161
+		case 5:
10162
+			if wireType != 2 {
10163
+				return fmt.Errorf("proto: wrong wireType = %d for field Runtimes", wireType)
10164
+			}
10165
+			var stringLen uint64
10166
+			for shift := uint(0); ; shift += 7 {
10167
+				if shift >= 64 {
10168
+					return ErrIntOverflowControl
10169
+				}
10170
+				if iNdEx >= l {
10171
+					return io.ErrUnexpectedEOF
10172
+				}
10173
+				b := dAtA[iNdEx]
10174
+				iNdEx++
10175
+				stringLen |= (uint64(b) & 0x7F) << shift
10176
+				if b < 0x80 {
10177
+					break
10178
+				}
10179
+			}
10180
+			intStringLen := int(stringLen)
10181
+			if intStringLen < 0 {
10182
+				return ErrInvalidLengthControl
10183
+			}
10184
+			postIndex := iNdEx + intStringLen
10185
+			if postIndex > l {
10186
+				return io.ErrUnexpectedEOF
10187
+			}
10188
+			m.Runtimes = append(m.Runtimes, string(dAtA[iNdEx:postIndex]))
10189
+			iNdEx = postIndex
10161 10190
 		default:
10162 10191
 			iNdEx = preIndex
10163 10192
 			skippy, err := skipControl(dAtA[iNdEx:])
... ...
@@ -13349,122 +13463,124 @@ var (
13349 13349
 func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
13350 13350
 
13351 13351
 var fileDescriptorControl = []byte{
13352
-	// 1865 bytes of a gzipped FileDescriptorProto
13353
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0x4b, 0x6f, 0x1b, 0x47,
13354
-	0x12, 0x16, 0x1f, 0x12, 0xa9, 0xa2, 0x48, 0x49, 0x2d, 0xda, 0x4b, 0xd0, 0x5e, 0x49, 0x18, 0xaf,
13355
-	0x65, 0x6a, 0xa1, 0xa5, 0xd6, 0xf4, 0x1a, 0xeb, 0xf5, 0x62, 0x1f, 0x96, 0x68, 0x3b, 0xb4, 0x6c,
13356
-	0xd9, 0x18, 0x49, 0x46, 0x6e, 0x04, 0x45, 0xb6, 0x95, 0x31, 0x29, 0x0e, 0x33, 0x33, 0x94, 0x2d,
13357
-	0xe4, 0x92, 0x04, 0xc9, 0x4f, 0x08, 0x90, 0x43, 0x7e, 0x41, 0x02, 0xe4, 0x90, 0x53, 0x6e, 0xb9,
13358
-	0x1a, 0x39, 0xe5, 0x98, 0x93, 0x10, 0x13, 0x08, 0x90, 0x53, 0x7e, 0x43, 0xd0, 0xaf, 0x79, 0xb1,
13359
-	0x67, 0x86, 0x94, 0x04, 0xc8, 0x27, 0xcf, 0xf4, 0x7c, 0xd5, 0x55, 0xdd, 0xf5, 0xf5, 0xc7, 0xea,
13360
-	0xb2, 0x20, 0xdb, 0xd4, 0xbb, 0x96, 0xa1, 0x77, 0xca, 0x3d, 0x43, 0xb7, 0x74, 0x84, 0x5a, 0x7a,
13361
-	0xb3, 0x8d, 0x8d, 0xb2, 0xf9, 0xaa, 0x61, 0x1c, 0xb6, 0x35, 0xab, 0x7c, 0x74, 0xb3, 0x98, 0x31,
13362
-	0x7b, 0xb8, 0x69, 0x32, 0x40, 0x31, 0xab, 0xef, 0xbf, 0xc4, 0x4d, 0x4b, 0xbc, 0x66, 0xac, 0xe3,
13363
-	0x1e, 0x16, 0x2f, 0xf9, 0x03, 0xfd, 0x40, 0xa7, 0x8f, 0xeb, 0xe4, 0x89, 0x8f, 0x2e, 0xf4, 0x3a,
13364
-	0xfd, 0x03, 0xad, 0xbb, 0xce, 0xfe, 0x61, 0x83, 0xca, 0x6d, 0xc8, 0x3d, 0xc4, 0xd6, 0xb6, 0xde,
13365
-	0xc2, 0x2a, 0xfe, 0xb0, 0x8f, 0x4d, 0x0b, 0x5d, 0x83, 0x54, 0x57, 0x6f, 0xe1, 0xba, 0xd6, 0x2a,
13366
-	0xc4, 0x96, 0x63, 0xa5, 0xe9, 0x0d, 0x18, 0x9c, 0x2c, 0x4d, 0x11, 0x44, 0xad, 0xaa, 0x4e, 0x91,
13367
-	0x4f, 0xb5, 0x96, 0xf2, 0x3f, 0x98, 0xb5, 0xcd, 0xcc, 0x9e, 0xde, 0x35, 0x31, 0x5a, 0x83, 0x24,
13368
-	0xf9, 0x48, 0x8d, 0x32, 0x95, 0x42, 0x79, 0x78, 0x01, 0x65, 0x8a, 0xa7, 0x28, 0xe5, 0x24, 0x01,
13369
-	0x73, 0x8f, 0x35, 0x93, 0x4e, 0x61, 0x0a, 0xd7, 0x0f, 0x20, 0xf5, 0x42, 0xeb, 0x58, 0xd8, 0x30,
13370
-	0xf9, 0x2c, 0x6b, 0xb2, 0x59, 0xfc, 0x66, 0xe5, 0x07, 0xcc, 0x46, 0x15, 0xc6, 0xc5, 0x4f, 0x12,
13371
-	0x90, 0xe2, 0x83, 0x28, 0x0f, 0x93, 0xdd, 0xc6, 0x21, 0x26, 0x33, 0x26, 0x4a, 0xd3, 0x2a, 0x7b,
13372
-	0x41, 0xeb, 0x90, 0xd1, 0x5a, 0xf5, 0x9e, 0x81, 0x5f, 0x68, 0xaf, 0xb1, 0x59, 0x88, 0x93, 0x6f,
13373
-	0x1b, 0xb9, 0xc1, 0xc9, 0x12, 0xd4, 0xaa, 0xcf, 0xf8, 0xa8, 0x0a, 0x5a, 0x4b, 0x3c, 0xa3, 0x67,
13374
-	0x30, 0xd5, 0x69, 0xec, 0xe3, 0x8e, 0x59, 0x48, 0x2c, 0x27, 0x4a, 0x99, 0xca, 0x9d, 0x71, 0x22,
13375
-	0x2b, 0x3f, 0xa6, 0xa6, 0xf7, 0xbb, 0x96, 0x71, 0xac, 0xf2, 0x79, 0x50, 0x0d, 0x32, 0x87, 0xf8,
13376
-	0x70, 0x1f, 0x1b, 0xe6, 0x07, 0x5a, 0xcf, 0x2c, 0x24, 0x97, 0x13, 0xa5, 0x5c, 0xe5, 0x46, 0xd0,
13377
-	0xb6, 0xed, 0xf4, 0x70, 0xb3, 0xfc, 0xc4, 0xc6, 0xab, 0x6e, 0x5b, 0x54, 0x81, 0x49, 0x43, 0xef,
13378
-	0x60, 0xb3, 0x30, 0x49, 0x27, 0xb9, 0x1a, 0xb8, 0xf7, 0x7a, 0x07, 0xab, 0x0c, 0x8a, 0xae, 0x41,
13379
-	0x96, 0x6c, 0x85, 0xb3, 0x07, 0x53, 0x74, 0x7f, 0x66, 0xc8, 0xa0, 0x58, 0x75, 0xf1, 0x5f, 0x90,
13380
-	0x71, 0x85, 0x8e, 0xe6, 0x20, 0xd1, 0xc6, 0xc7, 0x8c, 0x16, 0x2a, 0x79, 0x24, 0xbb, 0x7b, 0xd4,
13381
-	0xe8, 0xf4, 0x71, 0x21, 0x4e, 0xc7, 0xd8, 0xcb, 0xdd, 0xf8, 0x9d, 0x98, 0xb2, 0x09, 0xf3, 0xae,
13382
-	0xed, 0xe0, 0x1c, 0x29, 0xc3, 0x24, 0xc9, 0x3e, 0x4b, 0x46, 0x18, 0x49, 0x18, 0x4c, 0xf9, 0x3a,
13383
-	0x06, 0xf3, 0x7b, 0xbd, 0x56, 0xc3, 0xc2, 0xe3, 0x32, 0x14, 0xfd, 0x17, 0x66, 0x28, 0xe8, 0x08,
13384
-	0x1b, 0xa6, 0xa6, 0x77, 0x69, 0x80, 0x99, 0xca, 0x15, 0x99, 0xc7, 0xe7, 0x0c, 0xa2, 0x66, 0x88,
13385
-	0x01, 0x7f, 0x41, 0x7f, 0x87, 0x24, 0x39, 0x6e, 0x85, 0x04, 0xb5, 0xbb, 0x1a, 0x96, 0x17, 0x95,
13386
-	0x22, 0x95, 0x0d, 0x40, 0xee, 0x58, 0x4f, 0x75, 0x2c, 0xb6, 0x61, 0x5e, 0xc5, 0x87, 0xfa, 0xd1,
13387
-	0xf8, 0xeb, 0xcd, 0xc3, 0xe4, 0x0b, 0xdd, 0x68, 0xb2, 0x4c, 0xa4, 0x55, 0xf6, 0xa2, 0xe4, 0x01,
13388
-	0xb9, 0xe7, 0x63, 0x31, 0xf1, 0x43, 0xbf, 0xdb, 0x30, 0xdb, 0x2e, 0x17, 0x56, 0xc3, 0x6c, 0xfb,
13389
-	0x5c, 0x10, 0x04, 0x71, 0x41, 0x3e, 0xd9, 0x87, 0x9e, 0x99, 0x39, 0xab, 0x23, 0x1f, 0xc3, 0x56,
13390
-	0x47, 0xf1, 0x14, 0xa5, 0xdc, 0x11, 0xab, 0x1b, 0xdb, 0xb5, 0xbd, 0x0e, 0xb7, 0x77, 0xe5, 0xab,
13391
-	0x24, 0x13, 0x11, 0x32, 0x78, 0x0a, 0x11, 0x71, 0x9b, 0x0d, 0x8b, 0xc8, 0x0f, 0x17, 0x28, 0x22,
13392
-	0xb2, 0xc8, 0xa4, 0x22, 0xb2, 0x0e, 0x19, 0x13, 0x1b, 0x47, 0x5a, 0x93, 0xb0, 0x83, 0x89, 0x08,
13393
-	0x0f, 0x61, 0x87, 0x0d, 0xd7, 0xaa, 0xa6, 0x0a, 0x1c, 0x52, 0x6b, 0x99, 0x68, 0x05, 0xd2, 0x9c,
13394
-	0x4b, 0x4c, 0x2d, 0xa6, 0x37, 0x32, 0x83, 0x93, 0xa5, 0x14, 0x23, 0x93, 0xa9, 0xa6, 0x18, 0x9b,
13395
-	0x4c, 0x54, 0x85, 0x5c, 0x0b, 0x9b, 0x9a, 0x81, 0x5b, 0x75, 0xd3, 0x6a, 0x58, 0x5c, 0x1f, 0x72,
13396
-	0x95, 0x3f, 0x07, 0xa5, 0x78, 0x87, 0xa0, 0xd4, 0x2c, 0x37, 0xa2, 0x6f, 0x12, 0x91, 0x49, 0x0d,
13397
-	0x8b, 0x0c, 0xba, 0x0a, 0xd0, 0xef, 0xd5, 0x2d, 0xbd, 0x4e, 0xce, 0x4e, 0x21, 0x4d, 0xe9, 0x9b,
13398
-	0xee, 0xf7, 0x76, 0xf5, 0x6a, 0xc3, 0xc2, 0xe7, 0x20, 0x41, 0x7c, 0x33, 0x1d, 0x09, 0x22, 0x9c,
13399
-	0x0a, 0x95, 0x20, 0x4a, 0x32, 0x06, 0x53, 0xb6, 0x20, 0xbf, 0x69, 0xe0, 0x86, 0x85, 0xf9, 0x86,
13400
-	0x0a, 0x9a, 0xdd, 0xe2, 0xfa, 0xc0, 0x38, 0xb6, 0x24, 0x9b, 0x86, 0x5b, 0xb8, 0x24, 0x62, 0x1b,
13401
-	0x2e, 0xf9, 0x26, 0xe3, 0x51, 0xdd, 0x86, 0x14, 0x4f, 0x12, 0x9f, 0xf0, 0x4a, 0xc8, 0x84, 0xaa,
13402
-	0xc0, 0x2a, 0xf7, 0x60, 0xfe, 0x21, 0xb6, 0x7c, 0x91, 0xad, 0x01, 0x38, 0x9c, 0xe0, 0x67, 0x2a,
13403
-	0x3b, 0x38, 0x59, 0x9a, 0xb6, 0x29, 0xa1, 0x4e, 0xdb, 0x8c, 0x50, 0xb6, 0x00, 0xb9, 0xa7, 0x38,
13404
-	0x5b, 0x3c, 0xdf, 0xc5, 0x21, 0xcf, 0x34, 0xf0, 0x2c, 0x31, 0xa1, 0x2a, 0xcc, 0x0a, 0xf4, 0x18,
13405
-	0xf2, 0x9d, 0xe3, 0x36, 0x42, 0xc1, 0x6f, 0x79, 0x14, 0x7c, 0xb4, 0x0c, 0xa1, 0x27, 0x90, 0x36,
13406
-	0xf4, 0x4e, 0x67, 0xbf, 0xd1, 0x6c, 0x17, 0x92, 0xcb, 0xb1, 0x52, 0xae, 0x72, 0x53, 0x66, 0x28,
13407
-	0x5b, 0x64, 0x59, 0xe5, 0x86, 0xaa, 0x3d, 0x85, 0xa2, 0x40, 0x5a, 0x8c, 0xa2, 0x34, 0x24, 0xb7,
13408
-	0x9f, 0x6e, 0xdf, 0x9f, 0x9b, 0x40, 0x33, 0x90, 0x7e, 0xa6, 0xde, 0x7f, 0x5e, 0x7b, 0xba, 0xb7,
13409
-	0x33, 0x17, 0x23, 0xa4, 0xf0, 0x4d, 0x77, 0xb6, 0x24, 0x54, 0x21, 0xcf, 0xb4, 0xf2, 0x4c, 0xbc,
13410
-	0xf8, 0x13, 0x5c, 0xf2, 0xcd, 0xc2, 0x45, 0xf7, 0xb7, 0x38, 0x2c, 0x90, 0x63, 0xc5, 0xc7, 0x6d,
13411
-	0xdd, 0xad, 0xf9, 0x75, 0x77, 0x3d, 0x48, 0xdd, 0x7c, 0x96, 0xc3, 0xd2, 0xfb, 0x79, 0xfc, 0xdc,
13412
-	0xa5, 0x77, 0xc7, 0x27, 0xbd, 0xff, 0x1e, 0x33, 0x38, 0xa9, 0xfa, 0x0e, 0xc9, 0x5b, 0xf2, 0x7c,
13413
-	0x6b, 0xa8, 0xa7, 0x90, 0xf7, 0x86, 0xc4, 0x89, 0xf1, 0x4f, 0x48, 0xf3, 0x44, 0x09, 0x19, 0x0b,
13414
-	0x65, 0x86, 0x0d, 0x76, 0xc4, 0x6c, 0x1b, 0x5b, 0xaf, 0x74, 0xa3, 0x3d, 0x86, 0x98, 0x71, 0x0b,
13415
-	0x99, 0x98, 0xd9, 0x93, 0x39, 0xbc, 0xed, 0xb2, 0xa1, 0x30, 0xde, 0x0a, 0x2b, 0x81, 0x55, 0xf6,
13416
-	0xa8, 0x98, 0xf9, 0x22, 0x43, 0x90, 0x24, 0xbb, 0xc9, 0xf7, 0x8b, 0x3e, 0x13, 0x22, 0x73, 0x1b,
13417
-	0x42, 0xe4, 0xb8, 0x43, 0x64, 0x6e, 0x4b, 0x88, 0xcc, 0x01, 0xb6, 0xc0, 0x9d, 0x53, 0x8c, 0xef,
13418
-	0x8b, 0xb3, 0x75, 0xee, 0x61, 0xda, 0xe7, 0xcd, 0x17, 0xa9, 0x7d, 0xde, 0xf8, 0xf8, 0x29, 0xce,
13419
-	0x9b, 0xcf, 0xf2, 0xdd, 0x3a, 0x6f, 0x01, 0xc1, 0x5d, 0xe4, 0x79, 0x73, 0x42, 0x72, 0xce, 0x1b,
13420
-	0x4f, 0x54, 0xe8, 0x79, 0x13, 0x99, 0xb3, 0xc1, 0xfc, 0xf7, 0x79, 0xb3, 0xd3, 0x37, 0x2d, 0x6c,
13421
-	0xb8, 0x74, 0xb8, 0xc9, 0x46, 0x7c, 0x3a, 0xcc, 0x71, 0x84, 0x17, 0x1c, 0x60, 0xd3, 0xd7, 0x9e,
13422
-	0xc2, 0xa1, 0x2f, 0x87, 0x84, 0xd1, 0x57, 0x58, 0x09, 0xac, 0xcd, 0x25, 0xfe, 0xe1, 0x14, 0x5c,
13423
-	0xf2, 0x59, 0xbe, 0x5b, 0x5c, 0x0a, 0x08, 0xee, 0x22, 0xb9, 0xe4, 0x84, 0xe4, 0x70, 0x89, 0x67,
13424
-	0x23, 0x94, 0x4b, 0x22, 0x75, 0x36, 0x58, 0xf9, 0x22, 0x06, 0x99, 0x2d, 0x7c, 0xac, 0xea, 0x56,
13425
-	0xc3, 0x22, 0xe5, 0xcd, 0x5f, 0x61, 0x9e, 0x90, 0x0c, 0x1b, 0xf5, 0x97, 0xba, 0xd6, 0xad, 0x5b,
13426
-	0x7a, 0x1b, 0x77, 0x69, 0x68, 0x69, 0x75, 0x96, 0x7d, 0x78, 0xa4, 0x6b, 0xdd, 0x5d, 0x32, 0x8c,
13427
-	0xd6, 0x00, 0x1d, 0x36, 0xba, 0x8d, 0x03, 0x2f, 0x98, 0xdd, 0x14, 0xe7, 0xf8, 0x17, 0x29, 0xba,
13428
-	0xdf, 0xed, 0xe8, 0xcd, 0x76, 0x9d, 0xac, 0x3a, 0xe1, 0x41, 0xef, 0xd1, 0x0f, 0x5b, 0xf8, 0x58,
13429
-	0xf9, 0xd4, 0xae, 0xf9, 0xce, 0xc2, 0x73, 0x52, 0xf3, 0x09, 0xf4, 0x38, 0x35, 0x1f, 0xb7, 0x19,
13430
-	0xa3, 0xe6, 0xe3, 0xde, 0x5d, 0x35, 0xdf, 0x3d, 0x52, 0xf3, 0xb1, 0x5d, 0xa5, 0x35, 0x5f, 0x80,
13431
-	0xa1, 0x6b, 0xf3, 0x37, 0x92, 0x6f, 0x4e, 0x96, 0x26, 0x54, 0xdb, 0xcc, 0xa9, 0xe1, 0xce, 0xe9,
13432
-	0xa0, 0xfe, 0x07, 0xe6, 0x68, 0x55, 0xde, 0x34, 0xb0, 0x25, 0xf6, 0x73, 0x15, 0xa6, 0x4d, 0x3a,
13433
-	0xe0, 0x6c, 0xe7, 0xcc, 0xe0, 0x64, 0x29, 0xcd, 0x50, 0xb5, 0x2a, 0xf9, 0x9d, 0xa7, 0x4f, 0x2d,
13434
-	0xe5, 0x21, 0xbf, 0x17, 0x30, 0x73, 0x1e, 0x4a, 0x05, 0xa6, 0x18, 0x80, 0x47, 0x52, 0x94, 0xd7,
13435
-	0x0c, 0xd4, 0x86, 0x23, 0x95, 0xef, 0x63, 0xb0, 0x20, 0x8a, 0xd3, 0xd3, 0xc5, 0x82, 0x36, 0x20,
13436
-	0xc7, 0xa1, 0x63, 0xe4, 0x35, 0xcb, 0x4c, 0x44, 0x5a, 0x2b, 0x9e, 0xb4, 0x2e, 0x06, 0x07, 0xee,
13437
-	0x2a, 0x4f, 0x1e, 0x39, 0x57, 0x91, 0x33, 0x6f, 0xc3, 0xaf, 0x71, 0x40, 0xac, 0x12, 0x23, 0xaf,
13438
-	0xb6, 0x6c, 0xbe, 0xe7, 0x97, 0xcd, 0x72, 0x70, 0x55, 0xe9, 0x36, 0x1c, 0x56, 0xcd, 0xcf, 0xce,
13439
-	0x5f, 0x35, 0x55, 0x9f, 0x6a, 0xde, 0x1d, 0x2f, 0xb6, 0x0b, 0x11, 0xcd, 0x2d, 0x71, 0xb5, 0xe0,
13440
-	0x11, 0xf1, 0x94, 0xfd, 0x83, 0x5c, 0x84, 0xe8, 0x10, 0x97, 0xcc, 0xb0, 0x9c, 0x09, 0xa8, 0x52,
13441
-	0x83, 0x05, 0x71, 0xd9, 0x76, 0x53, 0xb7, 0xe2, 0xa9, 0x75, 0x47, 0xe6, 0x92, 0x77, 0xaa, 0x33,
13442
-	0x70, 0xe9, 0xff, 0xb0, 0x20, 0x2e, 0x56, 0xa7, 0x3c, 0xdd, 0x97, 0x9d, 0x0b, 0x9e, 0x3b, 0x9a,
13443
-	0xca, 0x37, 0x97, 0x21, 0xb5, 0xc9, 0xfe, 0x17, 0x01, 0x69, 0x90, 0xe2, 0x0d, 0x7a, 0xa4, 0xc8,
13444
-	0x82, 0xf2, 0x36, 0xfd, 0x8b, 0xd7, 0x42, 0x31, 0xbc, 0x12, 0xbd, 0xf4, 0xe3, 0xb7, 0xbf, 0x7f,
13445
-	0x19, 0x9f, 0x85, 0x2c, 0x05, 0xfd, 0x8d, 0xff, 0x12, 0x20, 0x1d, 0xa6, 0xed, 0x4e, 0x2f, 0xfa,
13446
-	0xcb, 0x28, 0x7d, 0xf1, 0xe2, 0xf5, 0x08, 0x54, 0xb8, 0x43, 0x03, 0xc0, 0x69, 0xb4, 0xa2, 0xeb,
13447
-	0xc1, 0xf7, 0x73, 0xf7, 0x0a, 0x57, 0xa2, 0x60, 0x91, 0x3e, 0x9d, 0x46, 0xaa, 0xdc, 0xe7, 0x50,
13448
-	0xe3, 0x56, 0xee, 0x53, 0xd2, 0x8f, 0x0d, 0xf0, 0xc9, 0x72, 0xb8, 0xdb, 0x30, 0xdb, 0x81, 0x39,
13449
-	0x74, 0x35, 0x52, 0x03, 0x73, 0xe8, 0x69, 0x99, 0x86, 0xe7, 0x90, 0xb6, 0xca, 0x82, 0x73, 0xe8,
13450
-	0x6e, 0x4b, 0x06, 0xe7, 0xd0, 0xd3, 0x6f, 0x8b, 0xdc, 0x4f, 0xba, 0xbc, 0x90, 0xfd, 0x74, 0xaf,
13451
-	0x70, 0x25, 0x0a, 0x16, 0xe9, 0xd3, 0x69, 0x75, 0xc9, 0x7d, 0x0e, 0x75, 0xd3, 0xe4, 0x3e, 0x87,
13452
-	0x3b, 0x66, 0x41, 0x3e, 0x5f, 0xc3, 0x8c, 0xfb, 0x0a, 0x8f, 0x6e, 0x8c, 0xd8, 0x77, 0x28, 0x96,
13453
-	0xa2, 0x81, 0xe1, 0x9e, 0x3f, 0x82, 0xac, 0xa7, 0xd7, 0x88, 0xa4, 0x33, 0xca, 0x7a, 0x9b, 0xc5,
13454
-	0xd5, 0x11, 0x90, 0x91, 0xce, 0x3d, 0x3d, 0x2d, 0xb9, 0x73, 0x59, 0x17, 0x4d, 0xee, 0x5c, 0xda,
13455
-	0x20, 0x0b, 0x71, 0xee, 0x69, 0x5d, 0xc9, 0x9d, 0xcb, 0x7a, 0x64, 0x72, 0xe7, 0xf2, 0x3e, 0x58,
13456
-	0x28, 0xc9, 0xf8, 0x55, 0x30, 0x90, 0x64, 0xde, 0xf6, 0x41, 0x20, 0xc9, 0xfc, 0xbd, 0x80, 0x70,
13457
-	0x92, 0x89, 0x7b, 0x6b, 0x30, 0xc9, 0x7c, 0x97, 0xed, 0x60, 0x92, 0xf9, 0xaf, 0xc0, 0x91, 0x24,
13458
-	0x13, 0x0b, 0x0e, 0x21, 0x99, 0x6f, 0xcd, 0xab, 0x23, 0x20, 0x47, 0xcc, 0x73, 0xa8, 0x73, 0x59,
13459
-	0xbf, 0x26, 0x2c, 0xcf, 0x23, 0x3a, 0x67, 0x79, 0xe6, 0x85, 0x7b, 0x60, 0x9e, 0xbd, 0x57, 0xa2,
13460
-	0xc0, 0x3c, 0xfb, 0x6e, 0x0d, 0x11, 0x79, 0x16, 0x77, 0xca, 0xe0, 0x3c, 0xfb, 0x2e, 0xc2, 0xc1,
13461
-	0x79, 0xf6, 0x5f, 0x4f, 0x23, 0xcf, 0xb3, 0x58, 0x70, 0xc8, 0x79, 0xf6, 0xad, 0x79, 0x75, 0x04,
13462
-	0x64, 0xe4, 0x8f, 0x93, 0x7d, 0x9b, 0x91, 0xff, 0x38, 0xf9, 0xef, 0x4a, 0xc5, 0xeb, 0x11, 0xa8,
13463
-	0xc8, 0x7d, 0x76, 0x5f, 0x1d, 0xe4, 0xfb, 0x2c, 0xb9, 0x16, 0x15, 0x4b, 0xd1, 0xc0, 0x70, 0xcf,
13464
-	0x7d, 0xc8, 0xb8, 0x0a, 0x60, 0xb4, 0x32, 0x5a, 0xcd, 0x5e, 0xbc, 0x11, 0x89, 0x8b, 0x5c, 0xb0,
13465
-	0xbb, 0xbe, 0x95, 0x2f, 0x58, 0x52, 0x4c, 0x17, 0x4b, 0xd1, 0xc0, 0x48, 0xcf, 0xee, 0x5a, 0x56,
13466
-	0xee, 0x59, 0x52, 0x2f, 0x17, 0x4b, 0xd1, 0xc0, 0x50, 0xcf, 0x1b, 0x85, 0x37, 0x6f, 0x17, 0x27,
13467
-	0x7e, 0x7e, 0xbb, 0x38, 0xf1, 0xf1, 0x60, 0x31, 0xf6, 0x66, 0xb0, 0x18, 0xfb, 0x69, 0xb0, 0x18,
13468
-	0xfb, 0x65, 0xb0, 0x18, 0xdb, 0x9f, 0xa2, 0x7f, 0x1a, 0x73, 0xeb, 0x8f, 0x00, 0x00, 0x00, 0xff,
13469
-	0xff, 0xcc, 0x5c, 0xf3, 0xfa, 0x93, 0x23, 0x00, 0x00,
13352
+	// 1894 bytes of a gzipped FileDescriptorProto
13353
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0x4f, 0x6f, 0xdb, 0x46,
13354
+	0x16, 0xb7, 0xfe, 0xd8, 0x92, 0x9e, 0x2c, 0xd9, 0x1e, 0x2b, 0x59, 0x41, 0xc9, 0xda, 0x06, 0xb3,
13355
+	0x71, 0xe4, 0x85, 0x57, 0xde, 0x28, 0x1b, 0x6c, 0x36, 0x8b, 0xfd, 0x13, 0x5b, 0x49, 0x56, 0x71,
13356
+	0xe2, 0x04, 0xb4, 0x1d, 0xec, 0x4d, 0x90, 0xa5, 0x89, 0xcb, 0x48, 0x16, 0x55, 0x92, 0x72, 0x62,
13357
+	0xf4, 0xd2, 0x16, 0xe9, 0x47, 0x28, 0xd0, 0x6b, 0xaf, 0x2d, 0xd0, 0x43, 0x4f, 0xf9, 0x08, 0x41,
13358
+	0x4f, 0x3d, 0x16, 0x28, 0x60, 0x34, 0x02, 0x0a, 0xf4, 0xd4, 0xcf, 0x50, 0xcc, 0x3f, 0x92, 0xa2,
13359
+	0x86, 0xa4, 0x64, 0x0b, 0x70, 0x4f, 0x21, 0x87, 0xbf, 0x37, 0xef, 0xcd, 0xbc, 0xdf, 0xfc, 0xf4,
13360
+	0xe6, 0x39, 0x90, 0x69, 0xe8, 0x1d, 0xcb, 0xd0, 0xdb, 0xa5, 0xae, 0xa1, 0x5b, 0x3a, 0x42, 0x4d,
13361
+	0xbd, 0xd1, 0xc2, 0x46, 0xc9, 0x7c, 0x55, 0x37, 0x8e, 0x5a, 0x9a, 0x55, 0x3a, 0xbe, 0x59, 0x48,
13362
+	0x9b, 0x5d, 0xdc, 0x30, 0x19, 0xa0, 0x90, 0xd1, 0x0f, 0x5e, 0xe2, 0x86, 0x25, 0x5e, 0xd3, 0xd6,
13363
+	0x49, 0x17, 0x8b, 0x97, 0xdc, 0xa1, 0x7e, 0xa8, 0xd3, 0xc7, 0x0d, 0xf2, 0xc4, 0x47, 0x17, 0xbb,
13364
+	0xed, 0xde, 0xa1, 0xd6, 0xd9, 0x60, 0xff, 0xb0, 0x41, 0xe5, 0x36, 0x64, 0x1f, 0x62, 0x6b, 0x47,
13365
+	0x6f, 0x62, 0x15, 0x7f, 0xd8, 0xc3, 0xa6, 0x85, 0xae, 0x41, 0xa2, 0xa3, 0x37, 0x71, 0x4d, 0x6b,
13366
+	0xe6, 0x23, 0x2b, 0x91, 0x62, 0x6a, 0x13, 0xfa, 0xa7, 0xcb, 0x33, 0x04, 0x51, 0xad, 0xa8, 0x33,
13367
+	0xe4, 0x53, 0xb5, 0xa9, 0xfc, 0x07, 0xe6, 0x6c, 0x33, 0xb3, 0xab, 0x77, 0x4c, 0x8c, 0xd6, 0x21,
13368
+	0x4e, 0x3e, 0x52, 0xa3, 0x74, 0x39, 0x5f, 0x1a, 0x5e, 0x40, 0x89, 0xe2, 0x29, 0x4a, 0x39, 0x8d,
13369
+	0xc1, 0xfc, 0x63, 0xcd, 0xa4, 0x53, 0x98, 0xc2, 0xf5, 0x03, 0x48, 0xbc, 0xd0, 0xda, 0x16, 0x36,
13370
+	0x4c, 0x3e, 0xcb, 0xba, 0x6c, 0x16, 0xaf, 0x59, 0xe9, 0x01, 0xb3, 0x51, 0x85, 0x71, 0xe1, 0x93,
13371
+	0x18, 0x24, 0xf8, 0x20, 0xca, 0xc1, 0x74, 0xa7, 0x7e, 0x84, 0xc9, 0x8c, 0xb1, 0x62, 0x4a, 0x65,
13372
+	0x2f, 0x68, 0x03, 0xd2, 0x5a, 0xb3, 0xd6, 0x35, 0xf0, 0x0b, 0xed, 0x35, 0x36, 0xf3, 0x51, 0xf2,
13373
+	0x6d, 0x33, 0xdb, 0x3f, 0x5d, 0x86, 0x6a, 0xe5, 0x19, 0x1f, 0x55, 0x41, 0x6b, 0x8a, 0x67, 0xf4,
13374
+	0x0c, 0x66, 0xda, 0xf5, 0x03, 0xdc, 0x36, 0xf3, 0xb1, 0x95, 0x58, 0x31, 0x5d, 0xbe, 0x33, 0x4e,
13375
+	0x64, 0xa5, 0xc7, 0xd4, 0xf4, 0x7e, 0xc7, 0x32, 0x4e, 0x54, 0x3e, 0x0f, 0xaa, 0x42, 0xfa, 0x08,
13376
+	0x1f, 0x1d, 0x60, 0xc3, 0xfc, 0x40, 0xeb, 0x9a, 0xf9, 0xf8, 0x4a, 0xac, 0x98, 0x2d, 0xdf, 0xf0,
13377
+	0xdb, 0xb6, 0xdd, 0x2e, 0x6e, 0x94, 0x9e, 0xd8, 0x78, 0xd5, 0x6d, 0x8b, 0xca, 0x30, 0x6d, 0xe8,
13378
+	0x6d, 0x6c, 0xe6, 0xa7, 0xe9, 0x24, 0x57, 0x7d, 0xf7, 0x5e, 0x6f, 0x63, 0x95, 0x41, 0xd1, 0x35,
13379
+	0xc8, 0x90, 0xad, 0x70, 0xf6, 0x60, 0x86, 0xee, 0xcf, 0x2c, 0x19, 0x14, 0xab, 0x2e, 0xfc, 0x03,
13380
+	0xd2, 0xae, 0xd0, 0xd1, 0x3c, 0xc4, 0x5a, 0xf8, 0x84, 0xd1, 0x42, 0x25, 0x8f, 0x64, 0x77, 0x8f,
13381
+	0xeb, 0xed, 0x1e, 0xce, 0x47, 0xe9, 0x18, 0x7b, 0xb9, 0x1b, 0xbd, 0x13, 0x51, 0xb6, 0x60, 0xc1,
13382
+	0xb5, 0x1d, 0x9c, 0x23, 0x25, 0x98, 0x26, 0xd9, 0x67, 0xc9, 0x08, 0x22, 0x09, 0x83, 0x29, 0x5f,
13383
+	0x45, 0x60, 0x61, 0xbf, 0xdb, 0xac, 0x5b, 0x78, 0x5c, 0x86, 0xa2, 0x7f, 0xc3, 0x2c, 0x05, 0x1d,
13384
+	0x63, 0xc3, 0xd4, 0xf4, 0x0e, 0x0d, 0x30, 0x5d, 0xbe, 0x22, 0xf3, 0xf8, 0x9c, 0x41, 0xd4, 0x34,
13385
+	0x31, 0xe0, 0x2f, 0xe8, 0xaf, 0x10, 0x27, 0xc7, 0x2d, 0x1f, 0xa3, 0x76, 0x57, 0x83, 0xf2, 0xa2,
13386
+	0x52, 0xa4, 0xb2, 0x09, 0xc8, 0x1d, 0xeb, 0x99, 0x8e, 0xc5, 0x0e, 0x2c, 0xa8, 0xf8, 0x48, 0x3f,
13387
+	0x1e, 0x7f, 0xbd, 0x39, 0x98, 0x7e, 0xa1, 0x1b, 0x0d, 0x96, 0x89, 0xa4, 0xca, 0x5e, 0x94, 0x1c,
13388
+	0x20, 0xf7, 0x7c, 0x2c, 0x26, 0x7e, 0xe8, 0xf7, 0xea, 0x66, 0xcb, 0xe5, 0xc2, 0xaa, 0x9b, 0x2d,
13389
+	0x8f, 0x0b, 0x82, 0x20, 0x2e, 0xc8, 0x27, 0xfb, 0xd0, 0x33, 0x33, 0x67, 0x75, 0xe4, 0x63, 0xd0,
13390
+	0xea, 0x28, 0x9e, 0xa2, 0x94, 0x3b, 0x62, 0x75, 0x63, 0xbb, 0xb6, 0xd7, 0xe1, 0xf6, 0xae, 0xbc,
13391
+	0x8d, 0x33, 0x11, 0x21, 0x83, 0x67, 0x10, 0x11, 0xb7, 0xd9, 0xb0, 0x88, 0xfc, 0x78, 0x81, 0x22,
13392
+	0x22, 0x8b, 0x4c, 0x2a, 0x22, 0x1b, 0x90, 0x36, 0xb1, 0x71, 0xac, 0x35, 0x08, 0x3b, 0x98, 0x88,
13393
+	0xf0, 0x10, 0x76, 0xd9, 0x70, 0xb5, 0x62, 0xaa, 0xc0, 0x21, 0xd5, 0xa6, 0x89, 0x56, 0x21, 0xc9,
13394
+	0xb9, 0xc4, 0xd4, 0x22, 0xb5, 0x99, 0xee, 0x9f, 0x2e, 0x27, 0x18, 0x99, 0x4c, 0x35, 0xc1, 0xd8,
13395
+	0x64, 0xa2, 0x0a, 0x64, 0x9b, 0xd8, 0xd4, 0x0c, 0xdc, 0xac, 0x99, 0x56, 0xdd, 0xe2, 0xfa, 0x90,
13396
+	0x2d, 0xff, 0xd1, 0x2f, 0xc5, 0xbb, 0x04, 0xa5, 0x66, 0xb8, 0x11, 0x7d, 0x93, 0x88, 0x4c, 0x62,
13397
+	0x58, 0x64, 0xd0, 0x55, 0x80, 0x5e, 0xb7, 0x66, 0xe9, 0x35, 0x72, 0x76, 0xf2, 0x49, 0x4a, 0xdf,
13398
+	0x64, 0xaf, 0xbb, 0xa7, 0x57, 0xea, 0x16, 0x46, 0x05, 0x48, 0x1a, 0xbd, 0x8e, 0xa5, 0x91, 0xdd,
13399
+	0x4f, 0x51, 0x6b, 0xfb, 0x7d, 0x02, 0xf2, 0xc4, 0x37, 0xda, 0x91, 0x27, 0xc2, 0xb7, 0x40, 0x79,
13400
+	0xa2, 0x04, 0x64, 0x30, 0x65, 0x1b, 0x72, 0x5b, 0x06, 0xae, 0x5b, 0x98, 0x6f, 0xb6, 0xa0, 0xe0,
13401
+	0x2d, 0xae, 0x1d, 0x8c, 0x7f, 0xcb, 0xb2, 0x69, 0xb8, 0x85, 0x4b, 0x3e, 0x76, 0xe0, 0x92, 0x67,
13402
+	0x32, 0x1e, 0xd5, 0x6d, 0x48, 0xf0, 0x04, 0xf2, 0x09, 0xaf, 0x04, 0x4c, 0xa8, 0x0a, 0xac, 0x72,
13403
+	0x0f, 0x16, 0x1e, 0x62, 0xcb, 0x13, 0xd9, 0x3a, 0x80, 0xc3, 0x17, 0x7e, 0xde, 0x32, 0xfd, 0xd3,
13404
+	0xe5, 0x94, 0x4d, 0x17, 0x35, 0x65, 0xb3, 0x45, 0xd9, 0x06, 0xe4, 0x9e, 0xe2, 0x7c, 0xf1, 0x7c,
13405
+	0x1b, 0x85, 0x1c, 0xd3, 0xc7, 0xf3, 0xc4, 0x84, 0x2a, 0x30, 0x27, 0xd0, 0x63, 0x48, 0x7b, 0x96,
13406
+	0xdb, 0x08, 0x75, 0xbf, 0x35, 0xa0, 0xee, 0xa3, 0x65, 0x08, 0x3d, 0x81, 0xa4, 0xa1, 0xb7, 0xdb,
13407
+	0x07, 0xf5, 0x46, 0x2b, 0x1f, 0x5f, 0x89, 0x14, 0xb3, 0xe5, 0x9b, 0x32, 0x43, 0xd9, 0x22, 0x4b,
13408
+	0x2a, 0x37, 0x54, 0xed, 0x29, 0x14, 0x05, 0x92, 0x62, 0x14, 0x25, 0x21, 0xbe, 0xf3, 0x74, 0xe7,
13409
+	0xfe, 0xfc, 0x14, 0x9a, 0x85, 0xe4, 0x33, 0xf5, 0xfe, 0xf3, 0xea, 0xd3, 0xfd, 0xdd, 0xf9, 0x08,
13410
+	0x21, 0x85, 0x67, 0xba, 0xf3, 0x25, 0xa1, 0x02, 0x39, 0xa6, 0xa3, 0xe7, 0xe2, 0xc5, 0x1f, 0xe0,
13411
+	0x92, 0x67, 0x16, 0x2e, 0xc8, 0x6f, 0x62, 0xb0, 0x48, 0x8e, 0x15, 0x1f, 0xb7, 0x35, 0xb9, 0xea,
13412
+	0xd5, 0xe4, 0x0d, 0x3f, 0xe5, 0xf3, 0x58, 0x0e, 0xcb, 0xf2, 0x97, 0xd1, 0x89, 0xcb, 0xf2, 0xae,
13413
+	0x47, 0x96, 0xff, 0x39, 0x66, 0x70, 0x52, 0x65, 0x1e, 0x92, 0xbe, 0xb8, 0x44, 0xfa, 0xdc, 0xe2,
13414
+	0x36, 0x3d, 0x39, 0x71, 0x7b, 0x0a, 0xb9, 0xc1, 0x70, 0x39, 0x69, 0xfe, 0x0e, 0x49, 0x9e, 0x44,
13415
+	0x21, 0x71, 0x81, 0xac, 0xb1, 0xc1, 0x8e, 0xd0, 0xed, 0x60, 0xeb, 0x95, 0x6e, 0xb4, 0xc6, 0x10,
13416
+	0x3a, 0x6e, 0x21, 0x13, 0x3a, 0x7b, 0x32, 0x87, 0xd3, 0x1d, 0x36, 0x14, 0xc4, 0x69, 0x61, 0x25,
13417
+	0xb0, 0xca, 0x3e, 0x15, 0x3a, 0x4f, 0x64, 0x08, 0xe2, 0x64, 0xa7, 0xf9, 0x7e, 0xd1, 0x67, 0x42,
13418
+	0x72, 0x6e, 0x43, 0x48, 0x1e, 0x75, 0x48, 0xce, 0x6d, 0x09, 0xc9, 0x39, 0xc0, 0x16, 0xbf, 0x09,
13419
+	0xc5, 0xf8, 0x7f, 0x71, 0xee, 0x26, 0x1e, 0xa6, 0x7d, 0x16, 0x3d, 0x91, 0x2a, 0xbf, 0x44, 0xd9,
13420
+	0x59, 0xe4, 0xe3, 0x67, 0x38, 0x8b, 0x1e, 0xcb, 0xe1, 0xb3, 0xf8, 0xd9, 0x05, 0x9e, 0x45, 0x9f,
13421
+	0xe0, 0xce, 0x7c, 0x16, 0x27, 0x70, 0xde, 0x9c, 0x90, 0x9c, 0xf3, 0xc6, 0x13, 0x15, 0x78, 0xde,
13422
+	0x44, 0xe6, 0x6c, 0x30, 0xff, 0xed, 0xde, 0x6a, 0xf7, 0x4c, 0x0b, 0x1b, 0x2e, 0x8d, 0x6e, 0xb0,
13423
+	0x11, 0x8f, 0x46, 0x73, 0x1c, 0xe1, 0x05, 0x07, 0xd8, 0xf4, 0xb5, 0xa7, 0x70, 0xe8, 0xcb, 0x21,
13424
+	0x41, 0xf4, 0x15, 0x56, 0x02, 0x6b, 0x73, 0x89, 0x7f, 0x38, 0x03, 0x97, 0x3c, 0x96, 0xbf, 0x2f,
13425
+	0x2e, 0xf9, 0x04, 0x77, 0x91, 0x5c, 0x72, 0x42, 0x72, 0xb8, 0xc4, 0xb3, 0x11, 0xc8, 0x25, 0x91,
13426
+	0x3a, 0x1b, 0xac, 0x7c, 0x1e, 0x81, 0xf4, 0x36, 0x3e, 0x51, 0x75, 0xab, 0x6e, 0x91, 0xd2, 0xe7,
13427
+	0xcf, 0xb0, 0x40, 0x48, 0x86, 0x8d, 0xda, 0x4b, 0x5d, 0xeb, 0xd4, 0x2c, 0xbd, 0x85, 0x3b, 0x34,
13428
+	0xb4, 0xa4, 0x3a, 0xc7, 0x3e, 0x3c, 0xd2, 0xb5, 0xce, 0x1e, 0x19, 0x46, 0xeb, 0x80, 0x8e, 0xea,
13429
+	0x9d, 0xfa, 0xe1, 0x20, 0x98, 0xdd, 0x30, 0xe7, 0xf9, 0x17, 0x29, 0xba, 0xd7, 0x69, 0xeb, 0x8d,
13430
+	0x56, 0x8d, 0xac, 0x3a, 0x36, 0x80, 0xde, 0xa7, 0x1f, 0xb6, 0xf1, 0x89, 0xf2, 0xa9, 0x5d, 0x0f,
13431
+	0x9e, 0x87, 0xe7, 0xa4, 0x1e, 0x14, 0xe8, 0x71, 0xea, 0x41, 0x6e, 0x33, 0x46, 0x3d, 0xc8, 0xbd,
13432
+	0xbb, 0xea, 0xc1, 0x7b, 0xa4, 0x1e, 0x64, 0xbb, 0x4a, 0xeb, 0x41, 0x1f, 0x43, 0xd7, 0xe6, 0x6f,
13433
+	0xc6, 0xdf, 0x9d, 0x2e, 0x4f, 0xa9, 0xb6, 0x99, 0x53, 0xdf, 0x4d, 0xe8, 0xa0, 0xfe, 0x0b, 0xe6,
13434
+	0x69, 0xc5, 0xde, 0x30, 0xb0, 0x25, 0xf6, 0x73, 0x0d, 0x52, 0x26, 0x1d, 0x70, 0xb6, 0x73, 0xb6,
13435
+	0x7f, 0xba, 0x9c, 0x64, 0xa8, 0x6a, 0x85, 0xfc, 0xce, 0xd3, 0xa7, 0xa6, 0xf2, 0x90, 0xdf, 0x19,
13436
+	0x98, 0x39, 0x0f, 0xa5, 0x0c, 0x33, 0x0c, 0xc0, 0x23, 0x29, 0xc8, 0x6b, 0x06, 0x6a, 0xc3, 0x91,
13437
+	0xca, 0xdb, 0x08, 0x2c, 0x8a, 0xc2, 0xf5, 0x6c, 0xb1, 0xa0, 0x4d, 0xc8, 0x72, 0xe8, 0x18, 0x79,
13438
+	0xcd, 0x30, 0x13, 0x91, 0xd6, 0xf2, 0x40, 0x5a, 0x97, 0xfc, 0x03, 0x77, 0x95, 0x27, 0x8f, 0x9c,
13439
+	0x6b, 0xca, 0xb9, 0xb7, 0xe1, 0xe7, 0x28, 0x20, 0x56, 0x89, 0x91, 0x57, 0x5b, 0x36, 0xff, 0xe7,
13440
+	0x95, 0xcd, 0x92, 0x7f, 0xc5, 0xe9, 0x36, 0x1c, 0x56, 0xcd, 0x37, 0x93, 0x57, 0x4d, 0xd5, 0xa3,
13441
+	0x9a, 0x77, 0xc7, 0x8b, 0xed, 0x42, 0x44, 0x73, 0x5b, 0x5c, 0x3b, 0x78, 0x44, 0x3c, 0x65, 0x7f,
13442
+	0x23, 0x97, 0x24, 0x3a, 0xc4, 0x25, 0x33, 0x28, 0x67, 0x02, 0xaa, 0x54, 0x61, 0x51, 0x5c, 0xc4,
13443
+	0xdd, 0xd4, 0x2d, 0x0f, 0xd4, 0xba, 0x23, 0x73, 0x69, 0x70, 0xaa, 0x73, 0x70, 0xe9, 0xbf, 0xb0,
13444
+	0x28, 0x2e, 0x5d, 0x67, 0x3c, 0xdd, 0x97, 0x9d, 0xcb, 0x9f, 0x3b, 0x9a, 0xf2, 0xd7, 0x97, 0x21,
13445
+	0xb1, 0xc5, 0xfe, 0xfa, 0x80, 0x34, 0x48, 0xf0, 0xc6, 0x3e, 0x52, 0x64, 0x41, 0x0d, 0xfe, 0xb1,
13446
+	0xa0, 0x70, 0x2d, 0x10, 0xc3, 0x2b, 0xd1, 0x4b, 0xdf, 0x7d, 0xf3, 0xeb, 0x17, 0xd1, 0x39, 0xc8,
13447
+	0x50, 0xd0, 0x5f, 0xf8, 0x2f, 0x01, 0xd2, 0x21, 0x65, 0x77, 0x88, 0xd1, 0x9f, 0x46, 0xe9, 0xa7,
13448
+	0x17, 0xae, 0x87, 0xa0, 0x82, 0x1d, 0x1a, 0x00, 0x4e, 0x83, 0x16, 0x5d, 0xf7, 0xbf, 0xbb, 0xbb,
13449
+	0x57, 0xb8, 0x1a, 0x06, 0x0b, 0xf5, 0xe9, 0x34, 0x60, 0xe5, 0x3e, 0x87, 0x1a, 0xbe, 0x72, 0x9f,
13450
+	0x92, 0x3e, 0xae, 0x8f, 0x4f, 0x96, 0xc3, 0xbd, 0xba, 0xd9, 0xf2, 0xcd, 0xa1, 0xab, 0x01, 0xeb,
13451
+	0x9b, 0xc3, 0x81, 0x56, 0x6b, 0x70, 0x0e, 0x69, 0x1b, 0xcd, 0x3f, 0x87, 0xee, 0x76, 0xa6, 0x7f,
13452
+	0x0e, 0x07, 0x7a, 0x71, 0xa1, 0xfb, 0x49, 0x97, 0x17, 0xb0, 0x9f, 0xee, 0x15, 0xae, 0x86, 0xc1,
13453
+	0x42, 0x7d, 0x3a, 0x6d, 0x30, 0xb9, 0xcf, 0xa1, 0x4e, 0x9b, 0xdc, 0xe7, 0x70, 0x37, 0xcd, 0xcf,
13454
+	0xe7, 0x6b, 0x98, 0x75, 0x5f, 0xe1, 0xd1, 0x8d, 0x11, 0x7b, 0x12, 0x85, 0x62, 0x38, 0x30, 0xd8,
13455
+	0xf3, 0x47, 0x90, 0x19, 0xe8, 0x43, 0x22, 0xe9, 0x8c, 0xb2, 0xbe, 0x67, 0x61, 0x6d, 0x04, 0x64,
13456
+	0xa8, 0xf3, 0x81, 0x7e, 0x97, 0xdc, 0xb9, 0xac, 0xc3, 0x26, 0x77, 0x2e, 0x6d, 0x9e, 0x05, 0x38,
13457
+	0x1f, 0x68, 0x6b, 0xc9, 0x9d, 0xcb, 0xfa, 0x67, 0x72, 0xe7, 0xf2, 0x1e, 0x59, 0x20, 0xc9, 0xf8,
13458
+	0x55, 0xd0, 0x97, 0x64, 0x83, 0xed, 0x03, 0x5f, 0x92, 0x79, 0x7b, 0x01, 0xc1, 0x24, 0x13, 0xf7,
13459
+	0x56, 0x7f, 0x92, 0x79, 0x2e, 0xdb, 0xfe, 0x24, 0xf3, 0x5e, 0x81, 0x43, 0x49, 0x26, 0x16, 0x1c,
13460
+	0x40, 0x32, 0xcf, 0x9a, 0xd7, 0x46, 0x40, 0x8e, 0x98, 0xe7, 0x40, 0xe7, 0xb2, 0x7e, 0x4d, 0x50,
13461
+	0x9e, 0x47, 0x74, 0xce, 0xf2, 0xcc, 0x0b, 0x77, 0xdf, 0x3c, 0x0f, 0x5e, 0x89, 0x7c, 0xf3, 0xec,
13462
+	0xb9, 0x35, 0x84, 0xe4, 0x59, 0xdc, 0x29, 0xfd, 0xf3, 0xec, 0xb9, 0x08, 0xfb, 0xe7, 0xd9, 0x7b,
13463
+	0x3d, 0x0d, 0x3d, 0xcf, 0x62, 0xc1, 0x01, 0xe7, 0xd9, 0xb3, 0xe6, 0xb5, 0x11, 0x90, 0xa1, 0x3f,
13464
+	0x4e, 0xf6, 0x6d, 0x46, 0xfe, 0xe3, 0xe4, 0xbd, 0x2b, 0x15, 0xae, 0x87, 0xa0, 0x42, 0xf7, 0xd9,
13465
+	0x7d, 0x75, 0x90, 0xef, 0xb3, 0xe4, 0x5a, 0x54, 0x28, 0x86, 0x03, 0x83, 0x3d, 0xf7, 0x20, 0xed,
13466
+	0x2a, 0x80, 0xd1, 0xea, 0x68, 0x35, 0x7b, 0xe1, 0x46, 0x28, 0x2e, 0x74, 0xc1, 0xee, 0xfa, 0x56,
13467
+	0xbe, 0x60, 0x49, 0x31, 0x5d, 0x28, 0x86, 0x03, 0x43, 0x3d, 0xbb, 0x6b, 0x59, 0xb9, 0x67, 0x49,
13468
+	0xbd, 0x5c, 0x28, 0x86, 0x03, 0x03, 0x3d, 0x6f, 0xe6, 0xdf, 0xbd, 0x5f, 0x9a, 0xfa, 0xe1, 0xfd,
13469
+	0xd2, 0xd4, 0xc7, 0xfd, 0xa5, 0xc8, 0xbb, 0xfe, 0x52, 0xe4, 0xfb, 0xfe, 0x52, 0xe4, 0xa7, 0xfe,
13470
+	0x52, 0xe4, 0x60, 0x86, 0xfe, 0x97, 0x9a, 0x5b, 0xbf, 0x05, 0x00, 0x00, 0xff, 0xff, 0x35, 0xa6,
13471
+	0x7d, 0x8d, 0xcb, 0x23, 0x00, 0x00,
13470 13472
 }
... ...
@@ -191,6 +191,8 @@ message ListTasksRequest {
191 191
 		repeated docker.swarmkit.v1.TaskState desired_states = 6;
192 192
 		// NamePrefixes matches all objects with the given prefixes
193 193
 		repeated string name_prefixes = 7;
194
+		repeated string runtimes = 9;
195
+
194 196
 		// UpToDate matches tasks that are consistent with the current
195 197
 		// service definition.
196 198
 		// Note: this is intended for internal status reporting rather
... ...
@@ -260,6 +262,7 @@ message ListServicesRequest {
260 260
 		map<string, string> labels = 3;
261 261
 		// NamePrefixes matches all objects with the given prefixes
262 262
 		repeated string name_prefixes = 4;
263
+		repeated string runtimes = 5;
263 264
 	}
264 265
 
265 266
 	Filters filters = 1;
... ...
@@ -26,6 +26,15 @@ type CopierFrom interface {
26 26
 // types that use this function.
27 27
 func Copy(dst, src interface{}) {
28 28
 	switch dst := dst.(type) {
29
+	case *types.Any:
30
+		src := src.(*types.Any)
31
+		dst.TypeUrl = src.TypeUrl
32
+		if src.Value != nil {
33
+			dst.Value = make([]byte, len(src.Value))
34
+			copy(dst.Value, src.Value)
35
+		} else {
36
+			dst.Value = nil
37
+		}
29 38
 	case *types.Duration:
30 39
 		src := src.(*types.Duration)
31 40
 		*dst = *src
... ...
@@ -1,6 +1,7 @@
1 1
 package equality
2 2
 
3 3
 import (
4
+	"crypto/subtle"
4 5
 	"reflect"
5 6
 
6 7
 	"github.com/docker/swarmkit/api"
... ...
@@ -27,3 +28,40 @@ func TaskStatusesEqualStable(a, b *api.TaskStatus) bool {
27 27
 	copyA.Timestamp, copyB.Timestamp = nil, nil
28 28
 	return reflect.DeepEqual(&copyA, &copyB)
29 29
 }
30
+
31
+// RootCAEqualStable compares RootCAs, excluding join tokens, which are randomly generated
32
+func RootCAEqualStable(a, b *api.RootCA) bool {
33
+	if a == nil && b == nil {
34
+		return true
35
+	}
36
+	if a == nil || b == nil {
37
+		return false
38
+	}
39
+
40
+	var aRotationKey, bRotationKey []byte
41
+	if a.RootRotation != nil {
42
+		aRotationKey = a.RootRotation.CAKey
43
+	}
44
+	if b.RootRotation != nil {
45
+		bRotationKey = b.RootRotation.CAKey
46
+	}
47
+	if subtle.ConstantTimeCompare(a.CAKey, b.CAKey) != 1 || subtle.ConstantTimeCompare(aRotationKey, bRotationKey) != 1 {
48
+		return false
49
+	}
50
+
51
+	copyA, copyB := *a, *b
52
+	copyA.JoinTokens, copyB.JoinTokens = api.JoinTokens{}, api.JoinTokens{}
53
+	return reflect.DeepEqual(copyA, copyB)
54
+}
55
+
56
+// ExternalCAsEqualStable compares lists of external CAs and determines whether they are equal.
57
+func ExternalCAsEqualStable(a, b []*api.ExternalCA) bool {
58
+	// because DeepEqual will treat an empty list and a nil list differently, we want to manually check this first
59
+	if len(a) == 0 && len(b) == 0 {
60
+		return true
61
+	}
62
+	// The assumption is that each individual api.ExternalCA within both lists are created from deserializing from a
63
+	// protobuf, so no special affordances are made to treat a nil map and empty map in the Options field of an
64
+	// api.ExternalCA as equivalent.
65
+	return reflect.DeepEqual(a, b)
66
+}
... ...
@@ -1,3 +1,3 @@
1 1
 package api
2 2
 
3
-//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf --gogoswarm_out=plugins=grpc+deepcopy+raftproxy+authenticatedwrapper,import_path=github.com/docker/swarmkit/api,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto logbroker.proto
3
+//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf --gogoswarm_out=plugins=grpc+deepcopy+storeobject+raftproxy+authenticatedwrapper,import_path=github.com/docker/swarmkit/api,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto logbroker.proto
... ...
@@ -2,11 +2,17 @@
2 2
 package naming
3 3
 
4 4
 import (
5
+	"errors"
5 6
 	"fmt"
7
+	"strings"
6 8
 
7 9
 	"github.com/docker/swarmkit/api"
8 10
 )
9 11
 
12
+var (
13
+	errUnknownRuntime = errors.New("unrecognized runtime")
14
+)
15
+
10 16
 // Task returns the task name from Annotations.Name,
11 17
 // and, in case Annotations.Name is missing, fallback
12 18
 // to construct the name from other information.
... ...
@@ -27,3 +33,17 @@ func Task(t *api.Task) string {
27 27
 }
28 28
 
29 29
 // TODO(stevvooe): Consolidate "Hostname" style validation here.
30
+
31
+// Runtime returns the runtime name from a given spec.
32
+func Runtime(t api.TaskSpec) (string, error) {
33
+	switch r := t.GetRuntime().(type) {
34
+	case *api.TaskSpec_Attachment:
35
+		return "attachment", nil
36
+	case *api.TaskSpec_Container:
37
+		return "container", nil
38
+	case *api.TaskSpec_Generic:
39
+		return strings.ToLower(r.Generic.Kind), nil
40
+	default:
41
+		return "", errUnknownRuntime
42
+	}
43
+}
... ...
@@ -9,10 +9,14 @@ import fmt "fmt"
9 9
 import math "math"
10 10
 import google_protobuf "github.com/gogo/protobuf/types"
11 11
 import _ "github.com/gogo/protobuf/gogoproto"
12
+import google_protobuf3 "github.com/gogo/protobuf/types"
13
+import _ "github.com/docker/swarmkit/protobuf/plugin"
12 14
 
13 15
 import github_com_docker_swarmkit_api_deepcopy "github.com/docker/swarmkit/api/deepcopy"
14 16
 
17
+import github_com_docker_go_events "github.com/docker/go-events"
15 18
 import strings "strings"
19
+
16 20
 import reflect "reflect"
17 21
 import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
18 22
 
... ...
@@ -77,9 +81,15 @@ type Service struct {
77 77
 	ID   string      `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
78 78
 	Meta Meta        `protobuf:"bytes,2,opt,name=meta" json:"meta"`
79 79
 	Spec ServiceSpec `protobuf:"bytes,3,opt,name=spec" json:"spec"`
80
+	// SpecVersion versions Spec, to identify changes in the spec. Note that
81
+	// this is not directly comparable to the service's Version.
82
+	SpecVersion *Version `protobuf:"bytes,10,opt,name=spec_version,json=specVersion" json:"spec_version,omitempty"`
80 83
 	// PreviousSpec is the previous service spec that was in place before
81 84
 	// "Spec".
82 85
 	PreviousSpec *ServiceSpec `protobuf:"bytes,6,opt,name=previous_spec,json=previousSpec" json:"previous_spec,omitempty"`
86
+	// PreviousSpecVersion versions PreviousSpec. Note that this is not
87
+	// directly comparable to the service's Version.
88
+	PreviousSpecVersion *Version `protobuf:"bytes,11,opt,name=previous_spec_version,json=previousSpecVersion" json:"previous_spec_version,omitempty"`
83 89
 	// Runtime state of service endpoint. This may be different
84 90
 	// from the spec version because the user may not have entered
85 91
 	// the optional fields like node_port or virtual_ip and it
... ...
@@ -140,6 +150,10 @@ type Task struct {
140 140
 	// Spec defines the desired state of the task as specified by the user.
141 141
 	// The system will honor this and will *never* modify it.
142 142
 	Spec TaskSpec `protobuf:"bytes,3,opt,name=spec" json:"spec"`
143
+	// SpecVersion is copied from Service, to identify which version of the
144
+	// spec this task has. Note that this is not directly comparable to the
145
+	// service's Version.
146
+	SpecVersion *Version `protobuf:"bytes,14,opt,name=spec_version,json=specVersion" json:"spec_version,omitempty"`
143 147
 	// ServiceID indicates the service under which this task is orchestrated. This
144 148
 	// should almost always be set.
145 149
 	ServiceID string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
... ...
@@ -272,6 +286,39 @@ func (m *Secret) Reset()                    { *m = Secret{} }
272 272
 func (*Secret) ProtoMessage()               {}
273 273
 func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorObjects, []int{8} }
274 274
 
275
+// Resource is a top-level object with externally defined content and indexing.
276
+// SwarmKit can serve as a store for these objects without understanding their
277
+// meanings.
278
+type Resource struct {
279
+	ID          string      `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
280
+	Meta        Meta        `protobuf:"bytes,2,opt,name=meta" json:"meta"`
281
+	Annotations Annotations `protobuf:"bytes,3,opt,name=annotations" json:"annotations"`
282
+	// Kind identifies this class of object. It is essentially a namespace
283
+	// to keep IDs or indices from colliding between unrelated Resource
284
+	// objects. This must correspond to the name of an Extension.
285
+	Kind string `protobuf:"bytes,4,opt,name=kind,proto3" json:"kind,omitempty"`
286
+	// Payload bytes. This data is not interpreted in any way by SwarmKit.
287
+	// By convention, it should be a marshalled protocol buffers message.
288
+	Payload *google_protobuf3.Any `protobuf:"bytes,5,opt,name=payload" json:"payload,omitempty"`
289
+}
290
+
291
+func (m *Resource) Reset()                    { *m = Resource{} }
292
+func (*Resource) ProtoMessage()               {}
293
+func (*Resource) Descriptor() ([]byte, []int) { return fileDescriptorObjects, []int{9} }
294
+
295
+// Extension declares a type of "resource" object. This message provides some
296
+// metadata about the objects.
297
+type Extension struct {
298
+	ID          string      `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
299
+	Meta        Meta        `protobuf:"bytes,2,opt,name=meta" json:"meta"`
300
+	Annotations Annotations `protobuf:"bytes,3,opt,name=annotations" json:"annotations"`
301
+	Description string      `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
302
+}
303
+
304
+func (m *Extension) Reset()                    { *m = Extension{} }
305
+func (*Extension) ProtoMessage()               {}
306
+func (*Extension) Descriptor() ([]byte, []int) { return fileDescriptorObjects, []int{10} }
307
+
275 308
 func init() {
276 309
 	proto.RegisterType((*Meta)(nil), "docker.swarmkit.v1.Meta")
277 310
 	proto.RegisterType((*Node)(nil), "docker.swarmkit.v1.Node")
... ...
@@ -283,6 +330,8 @@ func init() {
283 283
 	proto.RegisterType((*Network)(nil), "docker.swarmkit.v1.Network")
284 284
 	proto.RegisterType((*Cluster)(nil), "docker.swarmkit.v1.Cluster")
285 285
 	proto.RegisterType((*Secret)(nil), "docker.swarmkit.v1.Secret")
286
+	proto.RegisterType((*Resource)(nil), "docker.swarmkit.v1.Resource")
287
+	proto.RegisterType((*Extension)(nil), "docker.swarmkit.v1.Extension")
286 288
 }
287 289
 
288 290
 func (m *Meta) Copy() *Meta {
... ...
@@ -355,10 +404,18 @@ func (m *Service) CopyFrom(src interface{}) {
355 355
 	*m = *o
356 356
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Meta, &o.Meta)
357 357
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Spec, &o.Spec)
358
+	if o.SpecVersion != nil {
359
+		m.SpecVersion = &Version{}
360
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.SpecVersion, o.SpecVersion)
361
+	}
358 362
 	if o.PreviousSpec != nil {
359 363
 		m.PreviousSpec = &ServiceSpec{}
360 364
 		github_com_docker_swarmkit_api_deepcopy.Copy(m.PreviousSpec, o.PreviousSpec)
361 365
 	}
366
+	if o.PreviousSpecVersion != nil {
367
+		m.PreviousSpecVersion = &Version{}
368
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.PreviousSpecVersion, o.PreviousSpecVersion)
369
+	}
362 370
 	if o.Endpoint != nil {
363 371
 		m.Endpoint = &Endpoint{}
364 372
 		github_com_docker_swarmkit_api_deepcopy.Copy(m.Endpoint, o.Endpoint)
... ...
@@ -434,6 +491,10 @@ func (m *Task) CopyFrom(src interface{}) {
434 434
 	*m = *o
435 435
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Meta, &o.Meta)
436 436
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Spec, &o.Spec)
437
+	if o.SpecVersion != nil {
438
+		m.SpecVersion = &Version{}
439
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.SpecVersion, o.SpecVersion)
440
+	}
437 441
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Annotations, &o.Annotations)
438 442
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.ServiceAnnotations, &o.ServiceAnnotations)
439 443
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Status, &o.Status)
... ...
@@ -568,6 +629,44 @@ func (m *Secret) CopyFrom(src interface{}) {
568 568
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Spec, &o.Spec)
569 569
 }
570 570
 
571
+func (m *Resource) Copy() *Resource {
572
+	if m == nil {
573
+		return nil
574
+	}
575
+	o := &Resource{}
576
+	o.CopyFrom(m)
577
+	return o
578
+}
579
+
580
+func (m *Resource) CopyFrom(src interface{}) {
581
+
582
+	o := src.(*Resource)
583
+	*m = *o
584
+	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Meta, &o.Meta)
585
+	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Annotations, &o.Annotations)
586
+	if o.Payload != nil {
587
+		m.Payload = &google_protobuf3.Any{}
588
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.Payload, o.Payload)
589
+	}
590
+}
591
+
592
+func (m *Extension) Copy() *Extension {
593
+	if m == nil {
594
+		return nil
595
+	}
596
+	o := &Extension{}
597
+	o.CopyFrom(m)
598
+	return o
599
+}
600
+
601
+func (m *Extension) CopyFrom(src interface{}) {
602
+
603
+	o := src.(*Extension)
604
+	*m = *o
605
+	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Meta, &o.Meta)
606
+	github_com_docker_swarmkit_api_deepcopy.Copy(&m.Annotations, &o.Annotations)
607
+}
608
+
571 609
 func (m *Meta) Marshal() (dAtA []byte, err error) {
572 610
 	size := m.Size()
573 611
 	dAtA = make([]byte, size)
... ...
@@ -772,6 +871,26 @@ func (m *Service) MarshalTo(dAtA []byte) (int, error) {
772 772
 		}
773 773
 		i += n15
774 774
 	}
775
+	if m.SpecVersion != nil {
776
+		dAtA[i] = 0x52
777
+		i++
778
+		i = encodeVarintObjects(dAtA, i, uint64(m.SpecVersion.Size()))
779
+		n16, err := m.SpecVersion.MarshalTo(dAtA[i:])
780
+		if err != nil {
781
+			return 0, err
782
+		}
783
+		i += n16
784
+	}
785
+	if m.PreviousSpecVersion != nil {
786
+		dAtA[i] = 0x5a
787
+		i++
788
+		i = encodeVarintObjects(dAtA, i, uint64(m.PreviousSpecVersion.Size()))
789
+		n17, err := m.PreviousSpecVersion.MarshalTo(dAtA[i:])
790
+		if err != nil {
791
+			return 0, err
792
+		}
793
+		i += n17
794
+	}
775 795
 	return i, nil
776 796
 }
777 797
 
... ...
@@ -794,11 +913,11 @@ func (m *Endpoint) MarshalTo(dAtA []byte) (int, error) {
794 794
 		dAtA[i] = 0xa
795 795
 		i++
796 796
 		i = encodeVarintObjects(dAtA, i, uint64(m.Spec.Size()))
797
-		n16, err := m.Spec.MarshalTo(dAtA[i:])
797
+		n18, err := m.Spec.MarshalTo(dAtA[i:])
798 798
 		if err != nil {
799 799
 			return 0, err
800 800
 		}
801
-		i += n16
801
+		i += n18
802 802
 	}
803 803
 	if len(m.Ports) > 0 {
804 804
 		for _, msg := range m.Ports {
... ...
@@ -881,19 +1000,19 @@ func (m *Task) MarshalTo(dAtA []byte) (int, error) {
881 881
 	dAtA[i] = 0x12
882 882
 	i++
883 883
 	i = encodeVarintObjects(dAtA, i, uint64(m.Meta.Size()))
884
-	n17, err := m.Meta.MarshalTo(dAtA[i:])
884
+	n19, err := m.Meta.MarshalTo(dAtA[i:])
885 885
 	if err != nil {
886 886
 		return 0, err
887 887
 	}
888
-	i += n17
888
+	i += n19
889 889
 	dAtA[i] = 0x1a
890 890
 	i++
891 891
 	i = encodeVarintObjects(dAtA, i, uint64(m.Spec.Size()))
892
-	n18, err := m.Spec.MarshalTo(dAtA[i:])
892
+	n20, err := m.Spec.MarshalTo(dAtA[i:])
893 893
 	if err != nil {
894 894
 		return 0, err
895 895
 	}
896
-	i += n18
896
+	i += n20
897 897
 	if len(m.ServiceID) > 0 {
898 898
 		dAtA[i] = 0x22
899 899
 		i++
... ...
@@ -914,27 +1033,27 @@ func (m *Task) MarshalTo(dAtA []byte) (int, error) {
914 914
 	dAtA[i] = 0x3a
915 915
 	i++
916 916
 	i = encodeVarintObjects(dAtA, i, uint64(m.Annotations.Size()))
917
-	n19, err := m.Annotations.MarshalTo(dAtA[i:])
917
+	n21, err := m.Annotations.MarshalTo(dAtA[i:])
918 918
 	if err != nil {
919 919
 		return 0, err
920 920
 	}
921
-	i += n19
921
+	i += n21
922 922
 	dAtA[i] = 0x42
923 923
 	i++
924 924
 	i = encodeVarintObjects(dAtA, i, uint64(m.ServiceAnnotations.Size()))
925
-	n20, err := m.ServiceAnnotations.MarshalTo(dAtA[i:])
925
+	n22, err := m.ServiceAnnotations.MarshalTo(dAtA[i:])
926 926
 	if err != nil {
927 927
 		return 0, err
928 928
 	}
929
-	i += n20
929
+	i += n22
930 930
 	dAtA[i] = 0x4a
931 931
 	i++
932 932
 	i = encodeVarintObjects(dAtA, i, uint64(m.Status.Size()))
933
-	n21, err := m.Status.MarshalTo(dAtA[i:])
933
+	n23, err := m.Status.MarshalTo(dAtA[i:])
934 934
 	if err != nil {
935 935
 		return 0, err
936 936
 	}
937
-	i += n21
937
+	i += n23
938 938
 	if m.DesiredState != 0 {
939 939
 		dAtA[i] = 0x50
940 940
 		i++
... ...
@@ -956,21 +1075,31 @@ func (m *Task) MarshalTo(dAtA []byte) (int, error) {
956 956
 		dAtA[i] = 0x62
957 957
 		i++
958 958
 		i = encodeVarintObjects(dAtA, i, uint64(m.Endpoint.Size()))
959
-		n22, err := m.Endpoint.MarshalTo(dAtA[i:])
959
+		n24, err := m.Endpoint.MarshalTo(dAtA[i:])
960 960
 		if err != nil {
961 961
 			return 0, err
962 962
 		}
963
-		i += n22
963
+		i += n24
964 964
 	}
965 965
 	if m.LogDriver != nil {
966 966
 		dAtA[i] = 0x6a
967 967
 		i++
968 968
 		i = encodeVarintObjects(dAtA, i, uint64(m.LogDriver.Size()))
969
-		n23, err := m.LogDriver.MarshalTo(dAtA[i:])
969
+		n25, err := m.LogDriver.MarshalTo(dAtA[i:])
970 970
 		if err != nil {
971 971
 			return 0, err
972 972
 		}
973
-		i += n23
973
+		i += n25
974
+	}
975
+	if m.SpecVersion != nil {
976
+		dAtA[i] = 0x72
977
+		i++
978
+		i = encodeVarintObjects(dAtA, i, uint64(m.SpecVersion.Size()))
979
+		n26, err := m.SpecVersion.MarshalTo(dAtA[i:])
980
+		if err != nil {
981
+			return 0, err
982
+		}
983
+		i += n26
974 984
 	}
975 985
 	return i, nil
976 986
 }
... ...
@@ -994,11 +1123,11 @@ func (m *NetworkAttachment) MarshalTo(dAtA []byte) (int, error) {
994 994
 		dAtA[i] = 0xa
995 995
 		i++
996 996
 		i = encodeVarintObjects(dAtA, i, uint64(m.Network.Size()))
997
-		n24, err := m.Network.MarshalTo(dAtA[i:])
997
+		n27, err := m.Network.MarshalTo(dAtA[i:])
998 998
 		if err != nil {
999 999
 			return 0, err
1000 1000
 		}
1001
-		i += n24
1001
+		i += n27
1002 1002
 	}
1003 1003
 	if len(m.Addresses) > 0 {
1004 1004
 		for _, s := range m.Addresses {
... ...
@@ -1057,38 +1186,38 @@ func (m *Network) MarshalTo(dAtA []byte) (int, error) {
1057 1057
 	dAtA[i] = 0x12
1058 1058
 	i++
1059 1059
 	i = encodeVarintObjects(dAtA, i, uint64(m.Meta.Size()))
1060
-	n25, err := m.Meta.MarshalTo(dAtA[i:])
1060
+	n28, err := m.Meta.MarshalTo(dAtA[i:])
1061 1061
 	if err != nil {
1062 1062
 		return 0, err
1063 1063
 	}
1064
-	i += n25
1064
+	i += n28
1065 1065
 	dAtA[i] = 0x1a
1066 1066
 	i++
1067 1067
 	i = encodeVarintObjects(dAtA, i, uint64(m.Spec.Size()))
1068
-	n26, err := m.Spec.MarshalTo(dAtA[i:])
1068
+	n29, err := m.Spec.MarshalTo(dAtA[i:])
1069 1069
 	if err != nil {
1070 1070
 		return 0, err
1071 1071
 	}
1072
-	i += n26
1072
+	i += n29
1073 1073
 	if m.DriverState != nil {
1074 1074
 		dAtA[i] = 0x22
1075 1075
 		i++
1076 1076
 		i = encodeVarintObjects(dAtA, i, uint64(m.DriverState.Size()))
1077
-		n27, err := m.DriverState.MarshalTo(dAtA[i:])
1077
+		n30, err := m.DriverState.MarshalTo(dAtA[i:])
1078 1078
 		if err != nil {
1079 1079
 			return 0, err
1080 1080
 		}
1081
-		i += n27
1081
+		i += n30
1082 1082
 	}
1083 1083
 	if m.IPAM != nil {
1084 1084
 		dAtA[i] = 0x2a
1085 1085
 		i++
1086 1086
 		i = encodeVarintObjects(dAtA, i, uint64(m.IPAM.Size()))
1087
-		n28, err := m.IPAM.MarshalTo(dAtA[i:])
1087
+		n31, err := m.IPAM.MarshalTo(dAtA[i:])
1088 1088
 		if err != nil {
1089 1089
 			return 0, err
1090 1090
 		}
1091
-		i += n28
1091
+		i += n31
1092 1092
 	}
1093 1093
 	return i, nil
1094 1094
 }
... ...
@@ -1117,27 +1246,27 @@ func (m *Cluster) MarshalTo(dAtA []byte) (int, error) {
1117 1117
 	dAtA[i] = 0x12
1118 1118
 	i++
1119 1119
 	i = encodeVarintObjects(dAtA, i, uint64(m.Meta.Size()))
1120
-	n29, err := m.Meta.MarshalTo(dAtA[i:])
1120
+	n32, err := m.Meta.MarshalTo(dAtA[i:])
1121 1121
 	if err != nil {
1122 1122
 		return 0, err
1123 1123
 	}
1124
-	i += n29
1124
+	i += n32
1125 1125
 	dAtA[i] = 0x1a
1126 1126
 	i++
1127 1127
 	i = encodeVarintObjects(dAtA, i, uint64(m.Spec.Size()))
1128
-	n30, err := m.Spec.MarshalTo(dAtA[i:])
1128
+	n33, err := m.Spec.MarshalTo(dAtA[i:])
1129 1129
 	if err != nil {
1130 1130
 		return 0, err
1131 1131
 	}
1132
-	i += n30
1132
+	i += n33
1133 1133
 	dAtA[i] = 0x22
1134 1134
 	i++
1135 1135
 	i = encodeVarintObjects(dAtA, i, uint64(m.RootCA.Size()))
1136
-	n31, err := m.RootCA.MarshalTo(dAtA[i:])
1136
+	n34, err := m.RootCA.MarshalTo(dAtA[i:])
1137 1137
 	if err != nil {
1138 1138
 		return 0, err
1139 1139
 	}
1140
-	i += n31
1140
+	i += n34
1141 1141
 	if len(m.NetworkBootstrapKeys) > 0 {
1142 1142
 		for _, msg := range m.NetworkBootstrapKeys {
1143 1143
 			dAtA[i] = 0x2a
... ...
@@ -1175,11 +1304,11 @@ func (m *Cluster) MarshalTo(dAtA []byte) (int, error) {
1175 1175
 				dAtA[i] = 0x12
1176 1176
 				i++
1177 1177
 				i = encodeVarintObjects(dAtA, i, uint64(v.Size()))
1178
-				n32, err := v.MarshalTo(dAtA[i:])
1178
+				n35, err := v.MarshalTo(dAtA[i:])
1179 1179
 				if err != nil {
1180 1180
 					return 0, err
1181 1181
 				}
1182
-				i += n32
1182
+				i += n35
1183 1183
 			}
1184 1184
 		}
1185 1185
 	}
... ...
@@ -1222,19 +1351,19 @@ func (m *Secret) MarshalTo(dAtA []byte) (int, error) {
1222 1222
 	dAtA[i] = 0x12
1223 1223
 	i++
1224 1224
 	i = encodeVarintObjects(dAtA, i, uint64(m.Meta.Size()))
1225
-	n33, err := m.Meta.MarshalTo(dAtA[i:])
1225
+	n36, err := m.Meta.MarshalTo(dAtA[i:])
1226 1226
 	if err != nil {
1227 1227
 		return 0, err
1228 1228
 	}
1229
-	i += n33
1229
+	i += n36
1230 1230
 	dAtA[i] = 0x1a
1231 1231
 	i++
1232 1232
 	i = encodeVarintObjects(dAtA, i, uint64(m.Spec.Size()))
1233
-	n34, err := m.Spec.MarshalTo(dAtA[i:])
1233
+	n37, err := m.Spec.MarshalTo(dAtA[i:])
1234 1234
 	if err != nil {
1235 1235
 		return 0, err
1236 1236
 	}
1237
-	i += n34
1237
+	i += n37
1238 1238
 	if m.Internal {
1239 1239
 		dAtA[i] = 0x20
1240 1240
 		i++
... ...
@@ -1248,6 +1377,108 @@ func (m *Secret) MarshalTo(dAtA []byte) (int, error) {
1248 1248
 	return i, nil
1249 1249
 }
1250 1250
 
1251
+func (m *Resource) Marshal() (dAtA []byte, err error) {
1252
+	size := m.Size()
1253
+	dAtA = make([]byte, size)
1254
+	n, err := m.MarshalTo(dAtA)
1255
+	if err != nil {
1256
+		return nil, err
1257
+	}
1258
+	return dAtA[:n], nil
1259
+}
1260
+
1261
+func (m *Resource) MarshalTo(dAtA []byte) (int, error) {
1262
+	var i int
1263
+	_ = i
1264
+	var l int
1265
+	_ = l
1266
+	if len(m.ID) > 0 {
1267
+		dAtA[i] = 0xa
1268
+		i++
1269
+		i = encodeVarintObjects(dAtA, i, uint64(len(m.ID)))
1270
+		i += copy(dAtA[i:], m.ID)
1271
+	}
1272
+	dAtA[i] = 0x12
1273
+	i++
1274
+	i = encodeVarintObjects(dAtA, i, uint64(m.Meta.Size()))
1275
+	n38, err := m.Meta.MarshalTo(dAtA[i:])
1276
+	if err != nil {
1277
+		return 0, err
1278
+	}
1279
+	i += n38
1280
+	dAtA[i] = 0x1a
1281
+	i++
1282
+	i = encodeVarintObjects(dAtA, i, uint64(m.Annotations.Size()))
1283
+	n39, err := m.Annotations.MarshalTo(dAtA[i:])
1284
+	if err != nil {
1285
+		return 0, err
1286
+	}
1287
+	i += n39
1288
+	if len(m.Kind) > 0 {
1289
+		dAtA[i] = 0x22
1290
+		i++
1291
+		i = encodeVarintObjects(dAtA, i, uint64(len(m.Kind)))
1292
+		i += copy(dAtA[i:], m.Kind)
1293
+	}
1294
+	if m.Payload != nil {
1295
+		dAtA[i] = 0x2a
1296
+		i++
1297
+		i = encodeVarintObjects(dAtA, i, uint64(m.Payload.Size()))
1298
+		n40, err := m.Payload.MarshalTo(dAtA[i:])
1299
+		if err != nil {
1300
+			return 0, err
1301
+		}
1302
+		i += n40
1303
+	}
1304
+	return i, nil
1305
+}
1306
+
1307
+func (m *Extension) Marshal() (dAtA []byte, err error) {
1308
+	size := m.Size()
1309
+	dAtA = make([]byte, size)
1310
+	n, err := m.MarshalTo(dAtA)
1311
+	if err != nil {
1312
+		return nil, err
1313
+	}
1314
+	return dAtA[:n], nil
1315
+}
1316
+
1317
+func (m *Extension) MarshalTo(dAtA []byte) (int, error) {
1318
+	var i int
1319
+	_ = i
1320
+	var l int
1321
+	_ = l
1322
+	if len(m.ID) > 0 {
1323
+		dAtA[i] = 0xa
1324
+		i++
1325
+		i = encodeVarintObjects(dAtA, i, uint64(len(m.ID)))
1326
+		i += copy(dAtA[i:], m.ID)
1327
+	}
1328
+	dAtA[i] = 0x12
1329
+	i++
1330
+	i = encodeVarintObjects(dAtA, i, uint64(m.Meta.Size()))
1331
+	n41, err := m.Meta.MarshalTo(dAtA[i:])
1332
+	if err != nil {
1333
+		return 0, err
1334
+	}
1335
+	i += n41
1336
+	dAtA[i] = 0x1a
1337
+	i++
1338
+	i = encodeVarintObjects(dAtA, i, uint64(m.Annotations.Size()))
1339
+	n42, err := m.Annotations.MarshalTo(dAtA[i:])
1340
+	if err != nil {
1341
+		return 0, err
1342
+	}
1343
+	i += n42
1344
+	if len(m.Description) > 0 {
1345
+		dAtA[i] = 0x22
1346
+		i++
1347
+		i = encodeVarintObjects(dAtA, i, uint64(len(m.Description)))
1348
+		i += copy(dAtA[i:], m.Description)
1349
+	}
1350
+	return i, nil
1351
+}
1352
+
1251 1353
 func encodeFixed64Objects(dAtA []byte, offset int, v uint64) int {
1252 1354
 	dAtA[offset] = uint8(v)
1253 1355
 	dAtA[offset+1] = uint8(v >> 8)
... ...
@@ -1348,6 +1579,14 @@ func (m *Service) Size() (n int) {
1348 1348
 		l = m.PreviousSpec.Size()
1349 1349
 		n += 1 + l + sovObjects(uint64(l))
1350 1350
 	}
1351
+	if m.SpecVersion != nil {
1352
+		l = m.SpecVersion.Size()
1353
+		n += 1 + l + sovObjects(uint64(l))
1354
+	}
1355
+	if m.PreviousSpecVersion != nil {
1356
+		l = m.PreviousSpecVersion.Size()
1357
+		n += 1 + l + sovObjects(uint64(l))
1358
+	}
1351 1359
 	return n
1352 1360
 }
1353 1361
 
... ...
@@ -1432,6 +1671,10 @@ func (m *Task) Size() (n int) {
1432 1432
 		l = m.LogDriver.Size()
1433 1433
 		n += 1 + l + sovObjects(uint64(l))
1434 1434
 	}
1435
+	if m.SpecVersion != nil {
1436
+		l = m.SpecVersion.Size()
1437
+		n += 1 + l + sovObjects(uint64(l))
1438
+	}
1435 1439
 	return n
1436 1440
 }
1437 1441
 
... ...
@@ -1540,6 +1783,46 @@ func (m *Secret) Size() (n int) {
1540 1540
 	return n
1541 1541
 }
1542 1542
 
1543
+func (m *Resource) Size() (n int) {
1544
+	var l int
1545
+	_ = l
1546
+	l = len(m.ID)
1547
+	if l > 0 {
1548
+		n += 1 + l + sovObjects(uint64(l))
1549
+	}
1550
+	l = m.Meta.Size()
1551
+	n += 1 + l + sovObjects(uint64(l))
1552
+	l = m.Annotations.Size()
1553
+	n += 1 + l + sovObjects(uint64(l))
1554
+	l = len(m.Kind)
1555
+	if l > 0 {
1556
+		n += 1 + l + sovObjects(uint64(l))
1557
+	}
1558
+	if m.Payload != nil {
1559
+		l = m.Payload.Size()
1560
+		n += 1 + l + sovObjects(uint64(l))
1561
+	}
1562
+	return n
1563
+}
1564
+
1565
+func (m *Extension) Size() (n int) {
1566
+	var l int
1567
+	_ = l
1568
+	l = len(m.ID)
1569
+	if l > 0 {
1570
+		n += 1 + l + sovObjects(uint64(l))
1571
+	}
1572
+	l = m.Meta.Size()
1573
+	n += 1 + l + sovObjects(uint64(l))
1574
+	l = m.Annotations.Size()
1575
+	n += 1 + l + sovObjects(uint64(l))
1576
+	l = len(m.Description)
1577
+	if l > 0 {
1578
+		n += 1 + l + sovObjects(uint64(l))
1579
+	}
1580
+	return n
1581
+}
1582
+
1543 1583
 func sovObjects(x uint64) (n int) {
1544 1584
 	for {
1545 1585
 		n++
... ...
@@ -1553,6 +1836,1095 @@ func sovObjects(x uint64) (n int) {
1553 1553
 func sozObjects(x uint64) (n int) {
1554 1554
 	return sovObjects(uint64((x << 1) ^ uint64((int64(x) >> 63))))
1555 1555
 }
1556
+
1557
+type NodeCheckFunc func(t1, t2 *Node) bool
1558
+
1559
+type EventCreateNode struct {
1560
+	Node   *Node
1561
+	Checks []NodeCheckFunc
1562
+}
1563
+
1564
+func (e EventCreateNode) Matches(apiEvent github_com_docker_go_events.Event) bool {
1565
+	typedEvent, ok := apiEvent.(EventCreateNode)
1566
+	if !ok {
1567
+		return false
1568
+	}
1569
+
1570
+	for _, check := range e.Checks {
1571
+		if !check(e.Node, typedEvent.Node) {
1572
+			return false
1573
+		}
1574
+	}
1575
+	return true
1576
+}
1577
+
1578
+type EventUpdateNode struct {
1579
+	Node   *Node
1580
+	Checks []NodeCheckFunc
1581
+}
1582
+
1583
+func (e EventUpdateNode) Matches(apiEvent github_com_docker_go_events.Event) bool {
1584
+	typedEvent, ok := apiEvent.(EventUpdateNode)
1585
+	if !ok {
1586
+		return false
1587
+	}
1588
+
1589
+	for _, check := range e.Checks {
1590
+		if !check(e.Node, typedEvent.Node) {
1591
+			return false
1592
+		}
1593
+	}
1594
+	return true
1595
+}
1596
+
1597
+type EventDeleteNode struct {
1598
+	Node   *Node
1599
+	Checks []NodeCheckFunc
1600
+}
1601
+
1602
+func (e EventDeleteNode) Matches(apiEvent github_com_docker_go_events.Event) bool {
1603
+	typedEvent, ok := apiEvent.(EventDeleteNode)
1604
+	if !ok {
1605
+		return false
1606
+	}
1607
+
1608
+	for _, check := range e.Checks {
1609
+		if !check(e.Node, typedEvent.Node) {
1610
+			return false
1611
+		}
1612
+	}
1613
+	return true
1614
+}
1615
+func (m *Node) CopyStoreObject() StoreObject {
1616
+	return m.Copy()
1617
+}
1618
+
1619
+func (m *Node) GetMeta() Meta {
1620
+	return m.Meta
1621
+}
1622
+
1623
+func (m *Node) SetMeta(meta Meta) {
1624
+	m.Meta = meta
1625
+}
1626
+
1627
+func (m *Node) GetID() string {
1628
+	return m.ID
1629
+}
1630
+
1631
+func (m *Node) EventCreate() Event {
1632
+	return EventCreateNode{Node: m}
1633
+}
1634
+
1635
+func (m *Node) EventUpdate() Event {
1636
+	return EventUpdateNode{Node: m}
1637
+}
1638
+
1639
+func (m *Node) EventDelete() Event {
1640
+	return EventDeleteNode{Node: m}
1641
+}
1642
+
1643
+type NodeIndexerByID struct{}
1644
+
1645
+func (indexer NodeIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
1646
+	return fromArgs(args...)
1647
+}
1648
+func (indexer NodeIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1649
+	return prefixFromArgs(args...)
1650
+}
1651
+func (indexer NodeIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
1652
+	m := obj.(*Node)
1653
+	return true, []byte(m.ID + "\x00"), nil
1654
+}
1655
+
1656
+type NodeIndexerByName struct{}
1657
+
1658
+func (indexer NodeIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
1659
+	return fromArgs(args...)
1660
+}
1661
+func (indexer NodeIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1662
+	return prefixFromArgs(args...)
1663
+}
1664
+func (indexer NodeIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
1665
+	m := obj.(*Node)
1666
+	val := m.Spec.Annotations.Name
1667
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
1668
+}
1669
+
1670
+type NodeCustomIndexer struct{}
1671
+
1672
+func (indexer NodeCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
1673
+	return fromArgs(args...)
1674
+}
1675
+func (indexer NodeCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1676
+	return prefixFromArgs(args...)
1677
+}
1678
+func (indexer NodeCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
1679
+	m := obj.(*Node)
1680
+	return customIndexer("", &m.Spec.Annotations)
1681
+}
1682
+
1683
+type ServiceCheckFunc func(t1, t2 *Service) bool
1684
+
1685
+type EventCreateService struct {
1686
+	Service *Service
1687
+	Checks  []ServiceCheckFunc
1688
+}
1689
+
1690
+func (e EventCreateService) Matches(apiEvent github_com_docker_go_events.Event) bool {
1691
+	typedEvent, ok := apiEvent.(EventCreateService)
1692
+	if !ok {
1693
+		return false
1694
+	}
1695
+
1696
+	for _, check := range e.Checks {
1697
+		if !check(e.Service, typedEvent.Service) {
1698
+			return false
1699
+		}
1700
+	}
1701
+	return true
1702
+}
1703
+
1704
+type EventUpdateService struct {
1705
+	Service *Service
1706
+	Checks  []ServiceCheckFunc
1707
+}
1708
+
1709
+func (e EventUpdateService) Matches(apiEvent github_com_docker_go_events.Event) bool {
1710
+	typedEvent, ok := apiEvent.(EventUpdateService)
1711
+	if !ok {
1712
+		return false
1713
+	}
1714
+
1715
+	for _, check := range e.Checks {
1716
+		if !check(e.Service, typedEvent.Service) {
1717
+			return false
1718
+		}
1719
+	}
1720
+	return true
1721
+}
1722
+
1723
+type EventDeleteService struct {
1724
+	Service *Service
1725
+	Checks  []ServiceCheckFunc
1726
+}
1727
+
1728
+func (e EventDeleteService) Matches(apiEvent github_com_docker_go_events.Event) bool {
1729
+	typedEvent, ok := apiEvent.(EventDeleteService)
1730
+	if !ok {
1731
+		return false
1732
+	}
1733
+
1734
+	for _, check := range e.Checks {
1735
+		if !check(e.Service, typedEvent.Service) {
1736
+			return false
1737
+		}
1738
+	}
1739
+	return true
1740
+}
1741
+func (m *Service) CopyStoreObject() StoreObject {
1742
+	return m.Copy()
1743
+}
1744
+
1745
+func (m *Service) GetMeta() Meta {
1746
+	return m.Meta
1747
+}
1748
+
1749
+func (m *Service) SetMeta(meta Meta) {
1750
+	m.Meta = meta
1751
+}
1752
+
1753
+func (m *Service) GetID() string {
1754
+	return m.ID
1755
+}
1756
+
1757
+func (m *Service) EventCreate() Event {
1758
+	return EventCreateService{Service: m}
1759
+}
1760
+
1761
+func (m *Service) EventUpdate() Event {
1762
+	return EventUpdateService{Service: m}
1763
+}
1764
+
1765
+func (m *Service) EventDelete() Event {
1766
+	return EventDeleteService{Service: m}
1767
+}
1768
+
1769
+type ServiceIndexerByID struct{}
1770
+
1771
+func (indexer ServiceIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
1772
+	return fromArgs(args...)
1773
+}
1774
+func (indexer ServiceIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1775
+	return prefixFromArgs(args...)
1776
+}
1777
+func (indexer ServiceIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
1778
+	m := obj.(*Service)
1779
+	return true, []byte(m.ID + "\x00"), nil
1780
+}
1781
+
1782
+type ServiceIndexerByName struct{}
1783
+
1784
+func (indexer ServiceIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
1785
+	return fromArgs(args...)
1786
+}
1787
+func (indexer ServiceIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1788
+	return prefixFromArgs(args...)
1789
+}
1790
+func (indexer ServiceIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
1791
+	m := obj.(*Service)
1792
+	val := m.Spec.Annotations.Name
1793
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
1794
+}
1795
+
1796
+type ServiceCustomIndexer struct{}
1797
+
1798
+func (indexer ServiceCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
1799
+	return fromArgs(args...)
1800
+}
1801
+func (indexer ServiceCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1802
+	return prefixFromArgs(args...)
1803
+}
1804
+func (indexer ServiceCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
1805
+	m := obj.(*Service)
1806
+	return customIndexer("", &m.Spec.Annotations)
1807
+}
1808
+
1809
+type TaskCheckFunc func(t1, t2 *Task) bool
1810
+
1811
+type EventCreateTask struct {
1812
+	Task   *Task
1813
+	Checks []TaskCheckFunc
1814
+}
1815
+
1816
+func (e EventCreateTask) Matches(apiEvent github_com_docker_go_events.Event) bool {
1817
+	typedEvent, ok := apiEvent.(EventCreateTask)
1818
+	if !ok {
1819
+		return false
1820
+	}
1821
+
1822
+	for _, check := range e.Checks {
1823
+		if !check(e.Task, typedEvent.Task) {
1824
+			return false
1825
+		}
1826
+	}
1827
+	return true
1828
+}
1829
+
1830
+type EventUpdateTask struct {
1831
+	Task   *Task
1832
+	Checks []TaskCheckFunc
1833
+}
1834
+
1835
+func (e EventUpdateTask) Matches(apiEvent github_com_docker_go_events.Event) bool {
1836
+	typedEvent, ok := apiEvent.(EventUpdateTask)
1837
+	if !ok {
1838
+		return false
1839
+	}
1840
+
1841
+	for _, check := range e.Checks {
1842
+		if !check(e.Task, typedEvent.Task) {
1843
+			return false
1844
+		}
1845
+	}
1846
+	return true
1847
+}
1848
+
1849
+type EventDeleteTask struct {
1850
+	Task   *Task
1851
+	Checks []TaskCheckFunc
1852
+}
1853
+
1854
+func (e EventDeleteTask) Matches(apiEvent github_com_docker_go_events.Event) bool {
1855
+	typedEvent, ok := apiEvent.(EventDeleteTask)
1856
+	if !ok {
1857
+		return false
1858
+	}
1859
+
1860
+	for _, check := range e.Checks {
1861
+		if !check(e.Task, typedEvent.Task) {
1862
+			return false
1863
+		}
1864
+	}
1865
+	return true
1866
+}
1867
+func (m *Task) CopyStoreObject() StoreObject {
1868
+	return m.Copy()
1869
+}
1870
+
1871
+func (m *Task) GetMeta() Meta {
1872
+	return m.Meta
1873
+}
1874
+
1875
+func (m *Task) SetMeta(meta Meta) {
1876
+	m.Meta = meta
1877
+}
1878
+
1879
+func (m *Task) GetID() string {
1880
+	return m.ID
1881
+}
1882
+
1883
+func (m *Task) EventCreate() Event {
1884
+	return EventCreateTask{Task: m}
1885
+}
1886
+
1887
+func (m *Task) EventUpdate() Event {
1888
+	return EventUpdateTask{Task: m}
1889
+}
1890
+
1891
+func (m *Task) EventDelete() Event {
1892
+	return EventDeleteTask{Task: m}
1893
+}
1894
+
1895
+type TaskIndexerByID struct{}
1896
+
1897
+func (indexer TaskIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
1898
+	return fromArgs(args...)
1899
+}
1900
+func (indexer TaskIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1901
+	return prefixFromArgs(args...)
1902
+}
1903
+func (indexer TaskIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
1904
+	m := obj.(*Task)
1905
+	return true, []byte(m.ID + "\x00"), nil
1906
+}
1907
+
1908
+type TaskIndexerByName struct{}
1909
+
1910
+func (indexer TaskIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
1911
+	return fromArgs(args...)
1912
+}
1913
+func (indexer TaskIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1914
+	return prefixFromArgs(args...)
1915
+}
1916
+func (indexer TaskIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
1917
+	m := obj.(*Task)
1918
+	val := m.Annotations.Name
1919
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
1920
+}
1921
+
1922
+type TaskCustomIndexer struct{}
1923
+
1924
+func (indexer TaskCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
1925
+	return fromArgs(args...)
1926
+}
1927
+func (indexer TaskCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
1928
+	return prefixFromArgs(args...)
1929
+}
1930
+func (indexer TaskCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
1931
+	m := obj.(*Task)
1932
+	return customIndexer("", &m.Annotations)
1933
+}
1934
+
1935
+type NetworkCheckFunc func(t1, t2 *Network) bool
1936
+
1937
+type EventCreateNetwork struct {
1938
+	Network *Network
1939
+	Checks  []NetworkCheckFunc
1940
+}
1941
+
1942
+func (e EventCreateNetwork) Matches(apiEvent github_com_docker_go_events.Event) bool {
1943
+	typedEvent, ok := apiEvent.(EventCreateNetwork)
1944
+	if !ok {
1945
+		return false
1946
+	}
1947
+
1948
+	for _, check := range e.Checks {
1949
+		if !check(e.Network, typedEvent.Network) {
1950
+			return false
1951
+		}
1952
+	}
1953
+	return true
1954
+}
1955
+
1956
+type EventUpdateNetwork struct {
1957
+	Network *Network
1958
+	Checks  []NetworkCheckFunc
1959
+}
1960
+
1961
+func (e EventUpdateNetwork) Matches(apiEvent github_com_docker_go_events.Event) bool {
1962
+	typedEvent, ok := apiEvent.(EventUpdateNetwork)
1963
+	if !ok {
1964
+		return false
1965
+	}
1966
+
1967
+	for _, check := range e.Checks {
1968
+		if !check(e.Network, typedEvent.Network) {
1969
+			return false
1970
+		}
1971
+	}
1972
+	return true
1973
+}
1974
+
1975
+type EventDeleteNetwork struct {
1976
+	Network *Network
1977
+	Checks  []NetworkCheckFunc
1978
+}
1979
+
1980
+func (e EventDeleteNetwork) Matches(apiEvent github_com_docker_go_events.Event) bool {
1981
+	typedEvent, ok := apiEvent.(EventDeleteNetwork)
1982
+	if !ok {
1983
+		return false
1984
+	}
1985
+
1986
+	for _, check := range e.Checks {
1987
+		if !check(e.Network, typedEvent.Network) {
1988
+			return false
1989
+		}
1990
+	}
1991
+	return true
1992
+}
1993
+func (m *Network) CopyStoreObject() StoreObject {
1994
+	return m.Copy()
1995
+}
1996
+
1997
+func (m *Network) GetMeta() Meta {
1998
+	return m.Meta
1999
+}
2000
+
2001
+func (m *Network) SetMeta(meta Meta) {
2002
+	m.Meta = meta
2003
+}
2004
+
2005
+func (m *Network) GetID() string {
2006
+	return m.ID
2007
+}
2008
+
2009
+func (m *Network) EventCreate() Event {
2010
+	return EventCreateNetwork{Network: m}
2011
+}
2012
+
2013
+func (m *Network) EventUpdate() Event {
2014
+	return EventUpdateNetwork{Network: m}
2015
+}
2016
+
2017
+func (m *Network) EventDelete() Event {
2018
+	return EventDeleteNetwork{Network: m}
2019
+}
2020
+
2021
+type NetworkIndexerByID struct{}
2022
+
2023
+func (indexer NetworkIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
2024
+	return fromArgs(args...)
2025
+}
2026
+func (indexer NetworkIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2027
+	return prefixFromArgs(args...)
2028
+}
2029
+func (indexer NetworkIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
2030
+	m := obj.(*Network)
2031
+	return true, []byte(m.ID + "\x00"), nil
2032
+}
2033
+
2034
+type NetworkIndexerByName struct{}
2035
+
2036
+func (indexer NetworkIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
2037
+	return fromArgs(args...)
2038
+}
2039
+func (indexer NetworkIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2040
+	return prefixFromArgs(args...)
2041
+}
2042
+func (indexer NetworkIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
2043
+	m := obj.(*Network)
2044
+	val := m.Spec.Annotations.Name
2045
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
2046
+}
2047
+
2048
+type NetworkCustomIndexer struct{}
2049
+
2050
+func (indexer NetworkCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
2051
+	return fromArgs(args...)
2052
+}
2053
+func (indexer NetworkCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2054
+	return prefixFromArgs(args...)
2055
+}
2056
+func (indexer NetworkCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
2057
+	m := obj.(*Network)
2058
+	return customIndexer("", &m.Spec.Annotations)
2059
+}
2060
+
2061
+type ClusterCheckFunc func(t1, t2 *Cluster) bool
2062
+
2063
+type EventCreateCluster struct {
2064
+	Cluster *Cluster
2065
+	Checks  []ClusterCheckFunc
2066
+}
2067
+
2068
+func (e EventCreateCluster) Matches(apiEvent github_com_docker_go_events.Event) bool {
2069
+	typedEvent, ok := apiEvent.(EventCreateCluster)
2070
+	if !ok {
2071
+		return false
2072
+	}
2073
+
2074
+	for _, check := range e.Checks {
2075
+		if !check(e.Cluster, typedEvent.Cluster) {
2076
+			return false
2077
+		}
2078
+	}
2079
+	return true
2080
+}
2081
+
2082
+type EventUpdateCluster struct {
2083
+	Cluster *Cluster
2084
+	Checks  []ClusterCheckFunc
2085
+}
2086
+
2087
+func (e EventUpdateCluster) Matches(apiEvent github_com_docker_go_events.Event) bool {
2088
+	typedEvent, ok := apiEvent.(EventUpdateCluster)
2089
+	if !ok {
2090
+		return false
2091
+	}
2092
+
2093
+	for _, check := range e.Checks {
2094
+		if !check(e.Cluster, typedEvent.Cluster) {
2095
+			return false
2096
+		}
2097
+	}
2098
+	return true
2099
+}
2100
+
2101
+type EventDeleteCluster struct {
2102
+	Cluster *Cluster
2103
+	Checks  []ClusterCheckFunc
2104
+}
2105
+
2106
+func (e EventDeleteCluster) Matches(apiEvent github_com_docker_go_events.Event) bool {
2107
+	typedEvent, ok := apiEvent.(EventDeleteCluster)
2108
+	if !ok {
2109
+		return false
2110
+	}
2111
+
2112
+	for _, check := range e.Checks {
2113
+		if !check(e.Cluster, typedEvent.Cluster) {
2114
+			return false
2115
+		}
2116
+	}
2117
+	return true
2118
+}
2119
+func (m *Cluster) CopyStoreObject() StoreObject {
2120
+	return m.Copy()
2121
+}
2122
+
2123
+func (m *Cluster) GetMeta() Meta {
2124
+	return m.Meta
2125
+}
2126
+
2127
+func (m *Cluster) SetMeta(meta Meta) {
2128
+	m.Meta = meta
2129
+}
2130
+
2131
+func (m *Cluster) GetID() string {
2132
+	return m.ID
2133
+}
2134
+
2135
+func (m *Cluster) EventCreate() Event {
2136
+	return EventCreateCluster{Cluster: m}
2137
+}
2138
+
2139
+func (m *Cluster) EventUpdate() Event {
2140
+	return EventUpdateCluster{Cluster: m}
2141
+}
2142
+
2143
+func (m *Cluster) EventDelete() Event {
2144
+	return EventDeleteCluster{Cluster: m}
2145
+}
2146
+
2147
+type ClusterIndexerByID struct{}
2148
+
2149
+func (indexer ClusterIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
2150
+	return fromArgs(args...)
2151
+}
2152
+func (indexer ClusterIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2153
+	return prefixFromArgs(args...)
2154
+}
2155
+func (indexer ClusterIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
2156
+	m := obj.(*Cluster)
2157
+	return true, []byte(m.ID + "\x00"), nil
2158
+}
2159
+
2160
+type ClusterIndexerByName struct{}
2161
+
2162
+func (indexer ClusterIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
2163
+	return fromArgs(args...)
2164
+}
2165
+func (indexer ClusterIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2166
+	return prefixFromArgs(args...)
2167
+}
2168
+func (indexer ClusterIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
2169
+	m := obj.(*Cluster)
2170
+	val := m.Spec.Annotations.Name
2171
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
2172
+}
2173
+
2174
+type ClusterCustomIndexer struct{}
2175
+
2176
+func (indexer ClusterCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
2177
+	return fromArgs(args...)
2178
+}
2179
+func (indexer ClusterCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2180
+	return prefixFromArgs(args...)
2181
+}
2182
+func (indexer ClusterCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
2183
+	m := obj.(*Cluster)
2184
+	return customIndexer("", &m.Spec.Annotations)
2185
+}
2186
+
2187
+type SecretCheckFunc func(t1, t2 *Secret) bool
2188
+
2189
+type EventCreateSecret struct {
2190
+	Secret *Secret
2191
+	Checks []SecretCheckFunc
2192
+}
2193
+
2194
+func (e EventCreateSecret) Matches(apiEvent github_com_docker_go_events.Event) bool {
2195
+	typedEvent, ok := apiEvent.(EventCreateSecret)
2196
+	if !ok {
2197
+		return false
2198
+	}
2199
+
2200
+	for _, check := range e.Checks {
2201
+		if !check(e.Secret, typedEvent.Secret) {
2202
+			return false
2203
+		}
2204
+	}
2205
+	return true
2206
+}
2207
+
2208
+type EventUpdateSecret struct {
2209
+	Secret *Secret
2210
+	Checks []SecretCheckFunc
2211
+}
2212
+
2213
+func (e EventUpdateSecret) Matches(apiEvent github_com_docker_go_events.Event) bool {
2214
+	typedEvent, ok := apiEvent.(EventUpdateSecret)
2215
+	if !ok {
2216
+		return false
2217
+	}
2218
+
2219
+	for _, check := range e.Checks {
2220
+		if !check(e.Secret, typedEvent.Secret) {
2221
+			return false
2222
+		}
2223
+	}
2224
+	return true
2225
+}
2226
+
2227
+type EventDeleteSecret struct {
2228
+	Secret *Secret
2229
+	Checks []SecretCheckFunc
2230
+}
2231
+
2232
+func (e EventDeleteSecret) Matches(apiEvent github_com_docker_go_events.Event) bool {
2233
+	typedEvent, ok := apiEvent.(EventDeleteSecret)
2234
+	if !ok {
2235
+		return false
2236
+	}
2237
+
2238
+	for _, check := range e.Checks {
2239
+		if !check(e.Secret, typedEvent.Secret) {
2240
+			return false
2241
+		}
2242
+	}
2243
+	return true
2244
+}
2245
+func (m *Secret) CopyStoreObject() StoreObject {
2246
+	return m.Copy()
2247
+}
2248
+
2249
+func (m *Secret) GetMeta() Meta {
2250
+	return m.Meta
2251
+}
2252
+
2253
+func (m *Secret) SetMeta(meta Meta) {
2254
+	m.Meta = meta
2255
+}
2256
+
2257
+func (m *Secret) GetID() string {
2258
+	return m.ID
2259
+}
2260
+
2261
+func (m *Secret) EventCreate() Event {
2262
+	return EventCreateSecret{Secret: m}
2263
+}
2264
+
2265
+func (m *Secret) EventUpdate() Event {
2266
+	return EventUpdateSecret{Secret: m}
2267
+}
2268
+
2269
+func (m *Secret) EventDelete() Event {
2270
+	return EventDeleteSecret{Secret: m}
2271
+}
2272
+
2273
+type SecretIndexerByID struct{}
2274
+
2275
+func (indexer SecretIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
2276
+	return fromArgs(args...)
2277
+}
2278
+func (indexer SecretIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2279
+	return prefixFromArgs(args...)
2280
+}
2281
+func (indexer SecretIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
2282
+	m := obj.(*Secret)
2283
+	return true, []byte(m.ID + "\x00"), nil
2284
+}
2285
+
2286
+type SecretIndexerByName struct{}
2287
+
2288
+func (indexer SecretIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
2289
+	return fromArgs(args...)
2290
+}
2291
+func (indexer SecretIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2292
+	return prefixFromArgs(args...)
2293
+}
2294
+func (indexer SecretIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
2295
+	m := obj.(*Secret)
2296
+	val := m.Spec.Annotations.Name
2297
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
2298
+}
2299
+
2300
+type SecretCustomIndexer struct{}
2301
+
2302
+func (indexer SecretCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
2303
+	return fromArgs(args...)
2304
+}
2305
+func (indexer SecretCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2306
+	return prefixFromArgs(args...)
2307
+}
2308
+func (indexer SecretCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
2309
+	m := obj.(*Secret)
2310
+	return customIndexer("", &m.Spec.Annotations)
2311
+}
2312
+
2313
+type ResourceCheckFunc func(t1, t2 *Resource) bool
2314
+
2315
+type EventCreateResource struct {
2316
+	Resource *Resource
2317
+	Checks   []ResourceCheckFunc
2318
+}
2319
+
2320
+func (e EventCreateResource) Matches(apiEvent github_com_docker_go_events.Event) bool {
2321
+	typedEvent, ok := apiEvent.(EventCreateResource)
2322
+	if !ok {
2323
+		return false
2324
+	}
2325
+
2326
+	for _, check := range e.Checks {
2327
+		if !check(e.Resource, typedEvent.Resource) {
2328
+			return false
2329
+		}
2330
+	}
2331
+	return true
2332
+}
2333
+
2334
+type EventUpdateResource struct {
2335
+	Resource *Resource
2336
+	Checks   []ResourceCheckFunc
2337
+}
2338
+
2339
+func (e EventUpdateResource) Matches(apiEvent github_com_docker_go_events.Event) bool {
2340
+	typedEvent, ok := apiEvent.(EventUpdateResource)
2341
+	if !ok {
2342
+		return false
2343
+	}
2344
+
2345
+	for _, check := range e.Checks {
2346
+		if !check(e.Resource, typedEvent.Resource) {
2347
+			return false
2348
+		}
2349
+	}
2350
+	return true
2351
+}
2352
+
2353
+type EventDeleteResource struct {
2354
+	Resource *Resource
2355
+	Checks   []ResourceCheckFunc
2356
+}
2357
+
2358
+func (e EventDeleteResource) Matches(apiEvent github_com_docker_go_events.Event) bool {
2359
+	typedEvent, ok := apiEvent.(EventDeleteResource)
2360
+	if !ok {
2361
+		return false
2362
+	}
2363
+
2364
+	for _, check := range e.Checks {
2365
+		if !check(e.Resource, typedEvent.Resource) {
2366
+			return false
2367
+		}
2368
+	}
2369
+	return true
2370
+}
2371
+func (m *Resource) CopyStoreObject() StoreObject {
2372
+	return m.Copy()
2373
+}
2374
+
2375
+func (m *Resource) GetMeta() Meta {
2376
+	return m.Meta
2377
+}
2378
+
2379
+func (m *Resource) SetMeta(meta Meta) {
2380
+	m.Meta = meta
2381
+}
2382
+
2383
+func (m *Resource) GetID() string {
2384
+	return m.ID
2385
+}
2386
+
2387
+func (m *Resource) EventCreate() Event {
2388
+	return EventCreateResource{Resource: m}
2389
+}
2390
+
2391
+func (m *Resource) EventUpdate() Event {
2392
+	return EventUpdateResource{Resource: m}
2393
+}
2394
+
2395
+func (m *Resource) EventDelete() Event {
2396
+	return EventDeleteResource{Resource: m}
2397
+}
2398
+
2399
+type ResourceIndexerByID struct{}
2400
+
2401
+func (indexer ResourceIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
2402
+	return fromArgs(args...)
2403
+}
2404
+func (indexer ResourceIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2405
+	return prefixFromArgs(args...)
2406
+}
2407
+func (indexer ResourceIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
2408
+	m := obj.(*Resource)
2409
+	return true, []byte(m.ID + "\x00"), nil
2410
+}
2411
+
2412
+type ResourceIndexerByName struct{}
2413
+
2414
+func (indexer ResourceIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
2415
+	return fromArgs(args...)
2416
+}
2417
+func (indexer ResourceIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2418
+	return prefixFromArgs(args...)
2419
+}
2420
+func (indexer ResourceIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
2421
+	m := obj.(*Resource)
2422
+	val := m.Annotations.Name
2423
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
2424
+}
2425
+
2426
+type ResourceCustomIndexer struct{}
2427
+
2428
+func (indexer ResourceCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
2429
+	return fromArgs(args...)
2430
+}
2431
+func (indexer ResourceCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2432
+	return prefixFromArgs(args...)
2433
+}
2434
+func (indexer ResourceCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
2435
+	m := obj.(*Resource)
2436
+	return customIndexer("", &m.Annotations)
2437
+}
2438
+
2439
+type ExtensionCheckFunc func(t1, t2 *Extension) bool
2440
+
2441
+type EventCreateExtension struct {
2442
+	Extension *Extension
2443
+	Checks    []ExtensionCheckFunc
2444
+}
2445
+
2446
+func (e EventCreateExtension) Matches(apiEvent github_com_docker_go_events.Event) bool {
2447
+	typedEvent, ok := apiEvent.(EventCreateExtension)
2448
+	if !ok {
2449
+		return false
2450
+	}
2451
+
2452
+	for _, check := range e.Checks {
2453
+		if !check(e.Extension, typedEvent.Extension) {
2454
+			return false
2455
+		}
2456
+	}
2457
+	return true
2458
+}
2459
+
2460
+type EventUpdateExtension struct {
2461
+	Extension *Extension
2462
+	Checks    []ExtensionCheckFunc
2463
+}
2464
+
2465
+func (e EventUpdateExtension) Matches(apiEvent github_com_docker_go_events.Event) bool {
2466
+	typedEvent, ok := apiEvent.(EventUpdateExtension)
2467
+	if !ok {
2468
+		return false
2469
+	}
2470
+
2471
+	for _, check := range e.Checks {
2472
+		if !check(e.Extension, typedEvent.Extension) {
2473
+			return false
2474
+		}
2475
+	}
2476
+	return true
2477
+}
2478
+
2479
+type EventDeleteExtension struct {
2480
+	Extension *Extension
2481
+	Checks    []ExtensionCheckFunc
2482
+}
2483
+
2484
+func (e EventDeleteExtension) Matches(apiEvent github_com_docker_go_events.Event) bool {
2485
+	typedEvent, ok := apiEvent.(EventDeleteExtension)
2486
+	if !ok {
2487
+		return false
2488
+	}
2489
+
2490
+	for _, check := range e.Checks {
2491
+		if !check(e.Extension, typedEvent.Extension) {
2492
+			return false
2493
+		}
2494
+	}
2495
+	return true
2496
+}
2497
+func (m *Extension) CopyStoreObject() StoreObject {
2498
+	return m.Copy()
2499
+}
2500
+
2501
+func (m *Extension) GetMeta() Meta {
2502
+	return m.Meta
2503
+}
2504
+
2505
+func (m *Extension) SetMeta(meta Meta) {
2506
+	m.Meta = meta
2507
+}
2508
+
2509
+func (m *Extension) GetID() string {
2510
+	return m.ID
2511
+}
2512
+
2513
+func (m *Extension) EventCreate() Event {
2514
+	return EventCreateExtension{Extension: m}
2515
+}
2516
+
2517
+func (m *Extension) EventUpdate() Event {
2518
+	return EventUpdateExtension{Extension: m}
2519
+}
2520
+
2521
+func (m *Extension) EventDelete() Event {
2522
+	return EventDeleteExtension{Extension: m}
2523
+}
2524
+
2525
+type ExtensionIndexerByID struct{}
2526
+
2527
+func (indexer ExtensionIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
2528
+	return fromArgs(args...)
2529
+}
2530
+func (indexer ExtensionIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2531
+	return prefixFromArgs(args...)
2532
+}
2533
+func (indexer ExtensionIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
2534
+	m := obj.(*Extension)
2535
+	return true, []byte(m.ID + "\x00"), nil
2536
+}
2537
+
2538
+type ExtensionIndexerByName struct{}
2539
+
2540
+func (indexer ExtensionIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
2541
+	return fromArgs(args...)
2542
+}
2543
+func (indexer ExtensionIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2544
+	return prefixFromArgs(args...)
2545
+}
2546
+func (indexer ExtensionIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
2547
+	m := obj.(*Extension)
2548
+	val := m.Annotations.Name
2549
+	return true, []byte(strings.ToLower(val) + "\x00"), nil
2550
+}
2551
+
2552
+type ExtensionCustomIndexer struct{}
2553
+
2554
+func (indexer ExtensionCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
2555
+	return fromArgs(args...)
2556
+}
2557
+func (indexer ExtensionCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
2558
+	return prefixFromArgs(args...)
2559
+}
2560
+func (indexer ExtensionCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
2561
+	m := obj.(*Extension)
2562
+	return customIndexer("", &m.Annotations)
2563
+}
2564
+func NewStoreAction(c Event) (StoreAction, error) {
2565
+	var sa StoreAction
2566
+	switch v := c.(type) {
2567
+	case EventCreateNode:
2568
+		sa.Action = StoreActionKindCreate
2569
+		sa.Target = &StoreAction_Node{Node: v.Node}
2570
+	case EventUpdateNode:
2571
+		sa.Action = StoreActionKindUpdate
2572
+		sa.Target = &StoreAction_Node{Node: v.Node}
2573
+	case EventDeleteNode:
2574
+		sa.Action = StoreActionKindRemove
2575
+		sa.Target = &StoreAction_Node{Node: v.Node}
2576
+	case EventCreateService:
2577
+		sa.Action = StoreActionKindCreate
2578
+		sa.Target = &StoreAction_Service{Service: v.Service}
2579
+	case EventUpdateService:
2580
+		sa.Action = StoreActionKindUpdate
2581
+		sa.Target = &StoreAction_Service{Service: v.Service}
2582
+	case EventDeleteService:
2583
+		sa.Action = StoreActionKindRemove
2584
+		sa.Target = &StoreAction_Service{Service: v.Service}
2585
+	case EventCreateTask:
2586
+		sa.Action = StoreActionKindCreate
2587
+		sa.Target = &StoreAction_Task{Task: v.Task}
2588
+	case EventUpdateTask:
2589
+		sa.Action = StoreActionKindUpdate
2590
+		sa.Target = &StoreAction_Task{Task: v.Task}
2591
+	case EventDeleteTask:
2592
+		sa.Action = StoreActionKindRemove
2593
+		sa.Target = &StoreAction_Task{Task: v.Task}
2594
+	case EventCreateNetwork:
2595
+		sa.Action = StoreActionKindCreate
2596
+		sa.Target = &StoreAction_Network{Network: v.Network}
2597
+	case EventUpdateNetwork:
2598
+		sa.Action = StoreActionKindUpdate
2599
+		sa.Target = &StoreAction_Network{Network: v.Network}
2600
+	case EventDeleteNetwork:
2601
+		sa.Action = StoreActionKindRemove
2602
+		sa.Target = &StoreAction_Network{Network: v.Network}
2603
+	case EventCreateCluster:
2604
+		sa.Action = StoreActionKindCreate
2605
+		sa.Target = &StoreAction_Cluster{Cluster: v.Cluster}
2606
+	case EventUpdateCluster:
2607
+		sa.Action = StoreActionKindUpdate
2608
+		sa.Target = &StoreAction_Cluster{Cluster: v.Cluster}
2609
+	case EventDeleteCluster:
2610
+		sa.Action = StoreActionKindRemove
2611
+		sa.Target = &StoreAction_Cluster{Cluster: v.Cluster}
2612
+	case EventCreateSecret:
2613
+		sa.Action = StoreActionKindCreate
2614
+		sa.Target = &StoreAction_Secret{Secret: v.Secret}
2615
+	case EventUpdateSecret:
2616
+		sa.Action = StoreActionKindUpdate
2617
+		sa.Target = &StoreAction_Secret{Secret: v.Secret}
2618
+	case EventDeleteSecret:
2619
+		sa.Action = StoreActionKindRemove
2620
+		sa.Target = &StoreAction_Secret{Secret: v.Secret}
2621
+	case EventCreateResource:
2622
+		sa.Action = StoreActionKindCreate
2623
+		sa.Target = &StoreAction_Resource{Resource: v.Resource}
2624
+	case EventUpdateResource:
2625
+		sa.Action = StoreActionKindUpdate
2626
+		sa.Target = &StoreAction_Resource{Resource: v.Resource}
2627
+	case EventDeleteResource:
2628
+		sa.Action = StoreActionKindRemove
2629
+		sa.Target = &StoreAction_Resource{Resource: v.Resource}
2630
+	case EventCreateExtension:
2631
+		sa.Action = StoreActionKindCreate
2632
+		sa.Target = &StoreAction_Extension{Extension: v.Extension}
2633
+	case EventUpdateExtension:
2634
+		sa.Action = StoreActionKindUpdate
2635
+		sa.Target = &StoreAction_Extension{Extension: v.Extension}
2636
+	case EventDeleteExtension:
2637
+		sa.Action = StoreActionKindRemove
2638
+		sa.Target = &StoreAction_Extension{Extension: v.Extension}
2639
+	default:
2640
+		return StoreAction{}, errUnknownStoreAction
2641
+	}
2642
+	return sa, nil
2643
+}
2644
+
1556 2645
 func (this *Meta) String() string {
1557 2646
 	if this == nil {
1558 2647
 		return "nil"
... ...
@@ -1594,6 +2966,8 @@ func (this *Service) String() string {
1594 1594
 		`Endpoint:` + strings.Replace(fmt.Sprintf("%v", this.Endpoint), "Endpoint", "Endpoint", 1) + `,`,
1595 1595
 		`UpdateStatus:` + strings.Replace(fmt.Sprintf("%v", this.UpdateStatus), "UpdateStatus", "UpdateStatus", 1) + `,`,
1596 1596
 		`PreviousSpec:` + strings.Replace(fmt.Sprintf("%v", this.PreviousSpec), "ServiceSpec", "ServiceSpec", 1) + `,`,
1597
+		`SpecVersion:` + strings.Replace(fmt.Sprintf("%v", this.SpecVersion), "Version", "Version", 1) + `,`,
1598
+		`PreviousSpecVersion:` + strings.Replace(fmt.Sprintf("%v", this.PreviousSpecVersion), "Version", "Version", 1) + `,`,
1597 1599
 		`}`,
1598 1600
 	}, "")
1599 1601
 	return s
... ...
@@ -1639,6 +3013,7 @@ func (this *Task) String() string {
1639 1639
 		`Networks:` + strings.Replace(fmt.Sprintf("%v", this.Networks), "NetworkAttachment", "NetworkAttachment", 1) + `,`,
1640 1640
 		`Endpoint:` + strings.Replace(fmt.Sprintf("%v", this.Endpoint), "Endpoint", "Endpoint", 1) + `,`,
1641 1641
 		`LogDriver:` + strings.Replace(fmt.Sprintf("%v", this.LogDriver), "Driver", "Driver", 1) + `,`,
1642
+		`SpecVersion:` + strings.Replace(fmt.Sprintf("%v", this.SpecVersion), "Version", "Version", 1) + `,`,
1642 1643
 		`}`,
1643 1644
 	}, "")
1644 1645
 	return s
... ...
@@ -1709,6 +3084,33 @@ func (this *Secret) String() string {
1709 1709
 	}, "")
1710 1710
 	return s
1711 1711
 }
1712
+func (this *Resource) String() string {
1713
+	if this == nil {
1714
+		return "nil"
1715
+	}
1716
+	s := strings.Join([]string{`&Resource{`,
1717
+		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
1718
+		`Meta:` + strings.Replace(strings.Replace(this.Meta.String(), "Meta", "Meta", 1), `&`, ``, 1) + `,`,
1719
+		`Annotations:` + strings.Replace(strings.Replace(this.Annotations.String(), "Annotations", "Annotations", 1), `&`, ``, 1) + `,`,
1720
+		`Kind:` + fmt.Sprintf("%v", this.Kind) + `,`,
1721
+		`Payload:` + strings.Replace(fmt.Sprintf("%v", this.Payload), "Any", "google_protobuf3.Any", 1) + `,`,
1722
+		`}`,
1723
+	}, "")
1724
+	return s
1725
+}
1726
+func (this *Extension) String() string {
1727
+	if this == nil {
1728
+		return "nil"
1729
+	}
1730
+	s := strings.Join([]string{`&Extension{`,
1731
+		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
1732
+		`Meta:` + strings.Replace(strings.Replace(this.Meta.String(), "Meta", "Meta", 1), `&`, ``, 1) + `,`,
1733
+		`Annotations:` + strings.Replace(strings.Replace(this.Annotations.String(), "Annotations", "Annotations", 1), `&`, ``, 1) + `,`,
1734
+		`Description:` + fmt.Sprintf("%v", this.Description) + `,`,
1735
+		`}`,
1736
+	}, "")
1737
+	return s
1738
+}
1712 1739
 func valueToStringObjects(v interface{}) string {
1713 1740
 	rv := reflect.ValueOf(v)
1714 1741
 	if rv.IsNil() {
... ...
@@ -2397,6 +3799,72 @@ func (m *Service) Unmarshal(dAtA []byte) error {
2397 2397
 				return err
2398 2398
 			}
2399 2399
 			iNdEx = postIndex
2400
+		case 10:
2401
+			if wireType != 2 {
2402
+				return fmt.Errorf("proto: wrong wireType = %d for field SpecVersion", wireType)
2403
+			}
2404
+			var msglen int
2405
+			for shift := uint(0); ; shift += 7 {
2406
+				if shift >= 64 {
2407
+					return ErrIntOverflowObjects
2408
+				}
2409
+				if iNdEx >= l {
2410
+					return io.ErrUnexpectedEOF
2411
+				}
2412
+				b := dAtA[iNdEx]
2413
+				iNdEx++
2414
+				msglen |= (int(b) & 0x7F) << shift
2415
+				if b < 0x80 {
2416
+					break
2417
+				}
2418
+			}
2419
+			if msglen < 0 {
2420
+				return ErrInvalidLengthObjects
2421
+			}
2422
+			postIndex := iNdEx + msglen
2423
+			if postIndex > l {
2424
+				return io.ErrUnexpectedEOF
2425
+			}
2426
+			if m.SpecVersion == nil {
2427
+				m.SpecVersion = &Version{}
2428
+			}
2429
+			if err := m.SpecVersion.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
2430
+				return err
2431
+			}
2432
+			iNdEx = postIndex
2433
+		case 11:
2434
+			if wireType != 2 {
2435
+				return fmt.Errorf("proto: wrong wireType = %d for field PreviousSpecVersion", wireType)
2436
+			}
2437
+			var msglen int
2438
+			for shift := uint(0); ; shift += 7 {
2439
+				if shift >= 64 {
2440
+					return ErrIntOverflowObjects
2441
+				}
2442
+				if iNdEx >= l {
2443
+					return io.ErrUnexpectedEOF
2444
+				}
2445
+				b := dAtA[iNdEx]
2446
+				iNdEx++
2447
+				msglen |= (int(b) & 0x7F) << shift
2448
+				if b < 0x80 {
2449
+					break
2450
+				}
2451
+			}
2452
+			if msglen < 0 {
2453
+				return ErrInvalidLengthObjects
2454
+			}
2455
+			postIndex := iNdEx + msglen
2456
+			if postIndex > l {
2457
+				return io.ErrUnexpectedEOF
2458
+			}
2459
+			if m.PreviousSpecVersion == nil {
2460
+				m.PreviousSpecVersion = &Version{}
2461
+			}
2462
+			if err := m.PreviousSpecVersion.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
2463
+				return err
2464
+			}
2465
+			iNdEx = postIndex
2400 2466
 		default:
2401 2467
 			iNdEx = preIndex
2402 2468
 			skippy, err := skipObjects(dAtA[iNdEx:])
... ...
@@ -3072,6 +4540,39 @@ func (m *Task) Unmarshal(dAtA []byte) error {
3072 3072
 				return err
3073 3073
 			}
3074 3074
 			iNdEx = postIndex
3075
+		case 14:
3076
+			if wireType != 2 {
3077
+				return fmt.Errorf("proto: wrong wireType = %d for field SpecVersion", wireType)
3078
+			}
3079
+			var msglen int
3080
+			for shift := uint(0); ; shift += 7 {
3081
+				if shift >= 64 {
3082
+					return ErrIntOverflowObjects
3083
+				}
3084
+				if iNdEx >= l {
3085
+					return io.ErrUnexpectedEOF
3086
+				}
3087
+				b := dAtA[iNdEx]
3088
+				iNdEx++
3089
+				msglen |= (int(b) & 0x7F) << shift
3090
+				if b < 0x80 {
3091
+					break
3092
+				}
3093
+			}
3094
+			if msglen < 0 {
3095
+				return ErrInvalidLengthObjects
3096
+			}
3097
+			postIndex := iNdEx + msglen
3098
+			if postIndex > l {
3099
+				return io.ErrUnexpectedEOF
3100
+			}
3101
+			if m.SpecVersion == nil {
3102
+				m.SpecVersion = &Version{}
3103
+			}
3104
+			if err := m.SpecVersion.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3105
+				return err
3106
+			}
3107
+			iNdEx = postIndex
3075 3108
 		default:
3076 3109
 			iNdEx = preIndex
3077 3110
 			skippy, err := skipObjects(dAtA[iNdEx:])
... ...
@@ -3969,6 +5470,375 @@ func (m *Secret) Unmarshal(dAtA []byte) error {
3969 3969
 	}
3970 3970
 	return nil
3971 3971
 }
3972
+func (m *Resource) Unmarshal(dAtA []byte) error {
3973
+	l := len(dAtA)
3974
+	iNdEx := 0
3975
+	for iNdEx < l {
3976
+		preIndex := iNdEx
3977
+		var wire uint64
3978
+		for shift := uint(0); ; shift += 7 {
3979
+			if shift >= 64 {
3980
+				return ErrIntOverflowObjects
3981
+			}
3982
+			if iNdEx >= l {
3983
+				return io.ErrUnexpectedEOF
3984
+			}
3985
+			b := dAtA[iNdEx]
3986
+			iNdEx++
3987
+			wire |= (uint64(b) & 0x7F) << shift
3988
+			if b < 0x80 {
3989
+				break
3990
+			}
3991
+		}
3992
+		fieldNum := int32(wire >> 3)
3993
+		wireType := int(wire & 0x7)
3994
+		if wireType == 4 {
3995
+			return fmt.Errorf("proto: Resource: wiretype end group for non-group")
3996
+		}
3997
+		if fieldNum <= 0 {
3998
+			return fmt.Errorf("proto: Resource: illegal tag %d (wire type %d)", fieldNum, wire)
3999
+		}
4000
+		switch fieldNum {
4001
+		case 1:
4002
+			if wireType != 2 {
4003
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
4004
+			}
4005
+			var stringLen uint64
4006
+			for shift := uint(0); ; shift += 7 {
4007
+				if shift >= 64 {
4008
+					return ErrIntOverflowObjects
4009
+				}
4010
+				if iNdEx >= l {
4011
+					return io.ErrUnexpectedEOF
4012
+				}
4013
+				b := dAtA[iNdEx]
4014
+				iNdEx++
4015
+				stringLen |= (uint64(b) & 0x7F) << shift
4016
+				if b < 0x80 {
4017
+					break
4018
+				}
4019
+			}
4020
+			intStringLen := int(stringLen)
4021
+			if intStringLen < 0 {
4022
+				return ErrInvalidLengthObjects
4023
+			}
4024
+			postIndex := iNdEx + intStringLen
4025
+			if postIndex > l {
4026
+				return io.ErrUnexpectedEOF
4027
+			}
4028
+			m.ID = string(dAtA[iNdEx:postIndex])
4029
+			iNdEx = postIndex
4030
+		case 2:
4031
+			if wireType != 2 {
4032
+				return fmt.Errorf("proto: wrong wireType = %d for field Meta", wireType)
4033
+			}
4034
+			var msglen int
4035
+			for shift := uint(0); ; shift += 7 {
4036
+				if shift >= 64 {
4037
+					return ErrIntOverflowObjects
4038
+				}
4039
+				if iNdEx >= l {
4040
+					return io.ErrUnexpectedEOF
4041
+				}
4042
+				b := dAtA[iNdEx]
4043
+				iNdEx++
4044
+				msglen |= (int(b) & 0x7F) << shift
4045
+				if b < 0x80 {
4046
+					break
4047
+				}
4048
+			}
4049
+			if msglen < 0 {
4050
+				return ErrInvalidLengthObjects
4051
+			}
4052
+			postIndex := iNdEx + msglen
4053
+			if postIndex > l {
4054
+				return io.ErrUnexpectedEOF
4055
+			}
4056
+			if err := m.Meta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4057
+				return err
4058
+			}
4059
+			iNdEx = postIndex
4060
+		case 3:
4061
+			if wireType != 2 {
4062
+				return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType)
4063
+			}
4064
+			var msglen int
4065
+			for shift := uint(0); ; shift += 7 {
4066
+				if shift >= 64 {
4067
+					return ErrIntOverflowObjects
4068
+				}
4069
+				if iNdEx >= l {
4070
+					return io.ErrUnexpectedEOF
4071
+				}
4072
+				b := dAtA[iNdEx]
4073
+				iNdEx++
4074
+				msglen |= (int(b) & 0x7F) << shift
4075
+				if b < 0x80 {
4076
+					break
4077
+				}
4078
+			}
4079
+			if msglen < 0 {
4080
+				return ErrInvalidLengthObjects
4081
+			}
4082
+			postIndex := iNdEx + msglen
4083
+			if postIndex > l {
4084
+				return io.ErrUnexpectedEOF
4085
+			}
4086
+			if err := m.Annotations.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4087
+				return err
4088
+			}
4089
+			iNdEx = postIndex
4090
+		case 4:
4091
+			if wireType != 2 {
4092
+				return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
4093
+			}
4094
+			var stringLen uint64
4095
+			for shift := uint(0); ; shift += 7 {
4096
+				if shift >= 64 {
4097
+					return ErrIntOverflowObjects
4098
+				}
4099
+				if iNdEx >= l {
4100
+					return io.ErrUnexpectedEOF
4101
+				}
4102
+				b := dAtA[iNdEx]
4103
+				iNdEx++
4104
+				stringLen |= (uint64(b) & 0x7F) << shift
4105
+				if b < 0x80 {
4106
+					break
4107
+				}
4108
+			}
4109
+			intStringLen := int(stringLen)
4110
+			if intStringLen < 0 {
4111
+				return ErrInvalidLengthObjects
4112
+			}
4113
+			postIndex := iNdEx + intStringLen
4114
+			if postIndex > l {
4115
+				return io.ErrUnexpectedEOF
4116
+			}
4117
+			m.Kind = string(dAtA[iNdEx:postIndex])
4118
+			iNdEx = postIndex
4119
+		case 5:
4120
+			if wireType != 2 {
4121
+				return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
4122
+			}
4123
+			var msglen int
4124
+			for shift := uint(0); ; shift += 7 {
4125
+				if shift >= 64 {
4126
+					return ErrIntOverflowObjects
4127
+				}
4128
+				if iNdEx >= l {
4129
+					return io.ErrUnexpectedEOF
4130
+				}
4131
+				b := dAtA[iNdEx]
4132
+				iNdEx++
4133
+				msglen |= (int(b) & 0x7F) << shift
4134
+				if b < 0x80 {
4135
+					break
4136
+				}
4137
+			}
4138
+			if msglen < 0 {
4139
+				return ErrInvalidLengthObjects
4140
+			}
4141
+			postIndex := iNdEx + msglen
4142
+			if postIndex > l {
4143
+				return io.ErrUnexpectedEOF
4144
+			}
4145
+			if m.Payload == nil {
4146
+				m.Payload = &google_protobuf3.Any{}
4147
+			}
4148
+			if err := m.Payload.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4149
+				return err
4150
+			}
4151
+			iNdEx = postIndex
4152
+		default:
4153
+			iNdEx = preIndex
4154
+			skippy, err := skipObjects(dAtA[iNdEx:])
4155
+			if err != nil {
4156
+				return err
4157
+			}
4158
+			if skippy < 0 {
4159
+				return ErrInvalidLengthObjects
4160
+			}
4161
+			if (iNdEx + skippy) > l {
4162
+				return io.ErrUnexpectedEOF
4163
+			}
4164
+			iNdEx += skippy
4165
+		}
4166
+	}
4167
+
4168
+	if iNdEx > l {
4169
+		return io.ErrUnexpectedEOF
4170
+	}
4171
+	return nil
4172
+}
4173
+func (m *Extension) Unmarshal(dAtA []byte) error {
4174
+	l := len(dAtA)
4175
+	iNdEx := 0
4176
+	for iNdEx < l {
4177
+		preIndex := iNdEx
4178
+		var wire uint64
4179
+		for shift := uint(0); ; shift += 7 {
4180
+			if shift >= 64 {
4181
+				return ErrIntOverflowObjects
4182
+			}
4183
+			if iNdEx >= l {
4184
+				return io.ErrUnexpectedEOF
4185
+			}
4186
+			b := dAtA[iNdEx]
4187
+			iNdEx++
4188
+			wire |= (uint64(b) & 0x7F) << shift
4189
+			if b < 0x80 {
4190
+				break
4191
+			}
4192
+		}
4193
+		fieldNum := int32(wire >> 3)
4194
+		wireType := int(wire & 0x7)
4195
+		if wireType == 4 {
4196
+			return fmt.Errorf("proto: Extension: wiretype end group for non-group")
4197
+		}
4198
+		if fieldNum <= 0 {
4199
+			return fmt.Errorf("proto: Extension: illegal tag %d (wire type %d)", fieldNum, wire)
4200
+		}
4201
+		switch fieldNum {
4202
+		case 1:
4203
+			if wireType != 2 {
4204
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
4205
+			}
4206
+			var stringLen uint64
4207
+			for shift := uint(0); ; shift += 7 {
4208
+				if shift >= 64 {
4209
+					return ErrIntOverflowObjects
4210
+				}
4211
+				if iNdEx >= l {
4212
+					return io.ErrUnexpectedEOF
4213
+				}
4214
+				b := dAtA[iNdEx]
4215
+				iNdEx++
4216
+				stringLen |= (uint64(b) & 0x7F) << shift
4217
+				if b < 0x80 {
4218
+					break
4219
+				}
4220
+			}
4221
+			intStringLen := int(stringLen)
4222
+			if intStringLen < 0 {
4223
+				return ErrInvalidLengthObjects
4224
+			}
4225
+			postIndex := iNdEx + intStringLen
4226
+			if postIndex > l {
4227
+				return io.ErrUnexpectedEOF
4228
+			}
4229
+			m.ID = string(dAtA[iNdEx:postIndex])
4230
+			iNdEx = postIndex
4231
+		case 2:
4232
+			if wireType != 2 {
4233
+				return fmt.Errorf("proto: wrong wireType = %d for field Meta", wireType)
4234
+			}
4235
+			var msglen int
4236
+			for shift := uint(0); ; shift += 7 {
4237
+				if shift >= 64 {
4238
+					return ErrIntOverflowObjects
4239
+				}
4240
+				if iNdEx >= l {
4241
+					return io.ErrUnexpectedEOF
4242
+				}
4243
+				b := dAtA[iNdEx]
4244
+				iNdEx++
4245
+				msglen |= (int(b) & 0x7F) << shift
4246
+				if b < 0x80 {
4247
+					break
4248
+				}
4249
+			}
4250
+			if msglen < 0 {
4251
+				return ErrInvalidLengthObjects
4252
+			}
4253
+			postIndex := iNdEx + msglen
4254
+			if postIndex > l {
4255
+				return io.ErrUnexpectedEOF
4256
+			}
4257
+			if err := m.Meta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4258
+				return err
4259
+			}
4260
+			iNdEx = postIndex
4261
+		case 3:
4262
+			if wireType != 2 {
4263
+				return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType)
4264
+			}
4265
+			var msglen int
4266
+			for shift := uint(0); ; shift += 7 {
4267
+				if shift >= 64 {
4268
+					return ErrIntOverflowObjects
4269
+				}
4270
+				if iNdEx >= l {
4271
+					return io.ErrUnexpectedEOF
4272
+				}
4273
+				b := dAtA[iNdEx]
4274
+				iNdEx++
4275
+				msglen |= (int(b) & 0x7F) << shift
4276
+				if b < 0x80 {
4277
+					break
4278
+				}
4279
+			}
4280
+			if msglen < 0 {
4281
+				return ErrInvalidLengthObjects
4282
+			}
4283
+			postIndex := iNdEx + msglen
4284
+			if postIndex > l {
4285
+				return io.ErrUnexpectedEOF
4286
+			}
4287
+			if err := m.Annotations.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4288
+				return err
4289
+			}
4290
+			iNdEx = postIndex
4291
+		case 4:
4292
+			if wireType != 2 {
4293
+				return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType)
4294
+			}
4295
+			var stringLen uint64
4296
+			for shift := uint(0); ; shift += 7 {
4297
+				if shift >= 64 {
4298
+					return ErrIntOverflowObjects
4299
+				}
4300
+				if iNdEx >= l {
4301
+					return io.ErrUnexpectedEOF
4302
+				}
4303
+				b := dAtA[iNdEx]
4304
+				iNdEx++
4305
+				stringLen |= (uint64(b) & 0x7F) << shift
4306
+				if b < 0x80 {
4307
+					break
4308
+				}
4309
+			}
4310
+			intStringLen := int(stringLen)
4311
+			if intStringLen < 0 {
4312
+				return ErrInvalidLengthObjects
4313
+			}
4314
+			postIndex := iNdEx + intStringLen
4315
+			if postIndex > l {
4316
+				return io.ErrUnexpectedEOF
4317
+			}
4318
+			m.Description = string(dAtA[iNdEx:postIndex])
4319
+			iNdEx = postIndex
4320
+		default:
4321
+			iNdEx = preIndex
4322
+			skippy, err := skipObjects(dAtA[iNdEx:])
4323
+			if err != nil {
4324
+				return err
4325
+			}
4326
+			if skippy < 0 {
4327
+				return ErrInvalidLengthObjects
4328
+			}
4329
+			if (iNdEx + skippy) > l {
4330
+				return io.ErrUnexpectedEOF
4331
+			}
4332
+			iNdEx += skippy
4333
+		}
4334
+	}
4335
+
4336
+	if iNdEx > l {
4337
+		return io.ErrUnexpectedEOF
4338
+	}
4339
+	return nil
4340
+}
3972 4341
 func skipObjects(dAtA []byte) (n int, err error) {
3973 4342
 	l := len(dAtA)
3974 4343
 	iNdEx := 0
... ...
@@ -4077,79 +5947,89 @@ var (
4077 4077
 func init() { proto.RegisterFile("objects.proto", fileDescriptorObjects) }
4078 4078
 
4079 4079
 var fileDescriptorObjects = []byte{
4080
-	// 1183 bytes of a gzipped FileDescriptorProto
4081
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x57, 0xcd, 0x8e, 0x1b, 0x45,
4082
-	0x17, 0x4d, 0x7b, 0x7a, 0x6c, 0xf7, 0xf5, 0x78, 0xf4, 0x7d, 0x45, 0x14, 0x9a, 0x61, 0xb0, 0x07,
4083
-	0x47, 0xa0, 0x08, 0x45, 0x0e, 0x84, 0x80, 0x26, 0x40, 0x04, 0xb6, 0x67, 0x04, 0x56, 0x08, 0x44,
4084
-	0x95, 0x90, 0x2c, 0xad, 0x9a, 0xee, 0x8a, 0x69, 0xdc, 0xee, 0x6a, 0x55, 0x95, 0x1d, 0x79, 0x87,
4085
-	0x78, 0x00, 0x5e, 0x00, 0x09, 0xb1, 0xe6, 0x0d, 0x78, 0x83, 0x2c, 0x58, 0xb0, 0x83, 0x95, 0x45,
4086
-	0xfc, 0x24, 0xa8, 0x7e, 0xda, 0xee, 0x91, 0xdb, 0x4e, 0x22, 0x45, 0xd9, 0xd5, 0x75, 0x9d, 0x73,
4087
-	0xff, 0xea, 0xd4, 0xed, 0x32, 0xd4, 0xd9, 0xd9, 0x0f, 0x34, 0x90, 0xa2, 0x9d, 0x72, 0x26, 0x19,
4088
-	0x42, 0x21, 0x0b, 0x46, 0x94, 0xb7, 0xc5, 0x63, 0xc2, 0xc7, 0xa3, 0x48, 0xb6, 0xa7, 0x1f, 0x1c,
4089
-	0xd4, 0xe4, 0x2c, 0xa5, 0x16, 0x70, 0x50, 0x13, 0x29, 0x0d, 0x32, 0xa3, 0x39, 0x64, 0x6c, 0x18,
4090
-	0xd3, 0x6b, 0xda, 0x3a, 0x9b, 0x3c, 0xba, 0x26, 0xa3, 0x31, 0x15, 0x92, 0x8c, 0x53, 0x0b, 0xb8,
4091
-	0x38, 0x64, 0x43, 0xa6, 0x97, 0xd7, 0xd4, 0xca, 0xfc, 0xda, 0xfa, 0xc3, 0x01, 0xf7, 0x0e, 0x95,
4092
-	0x04, 0x7d, 0x0a, 0x95, 0x29, 0xe5, 0x22, 0x62, 0x89, 0xef, 0x1c, 0x39, 0x57, 0x6a, 0xd7, 0xdf,
4093
-	0x6c, 0xaf, 0xc7, 0x6f, 0x3f, 0x30, 0x90, 0xae, 0xfb, 0x64, 0xde, 0xbc, 0x80, 0x33, 0x06, 0xba,
4094
-	0x09, 0x10, 0x70, 0x4a, 0x24, 0x0d, 0x07, 0x44, 0xfa, 0x25, 0xcd, 0x3f, 0x68, 0x9b, 0x8c, 0xda,
4095
-	0x59, 0x46, 0xed, 0xfb, 0x59, 0x46, 0xd8, 0xb3, 0xe8, 0x8e, 0x54, 0xd4, 0x49, 0x1a, 0x66, 0xd4,
4096
-	0x9d, 0x67, 0x53, 0x2d, 0xba, 0x23, 0x5b, 0xbf, 0xb8, 0xe0, 0x7e, 0xc3, 0x42, 0x8a, 0x2e, 0x41,
4097
-	0x29, 0x0a, 0x75, 0xda, 0x5e, 0xb7, 0xbc, 0x98, 0x37, 0x4b, 0xfd, 0x13, 0x5c, 0x8a, 0x42, 0x74,
4098
-	0x1d, 0xdc, 0x31, 0x95, 0xc4, 0x26, 0xe4, 0x17, 0x15, 0xa4, 0x6a, 0xb7, 0xd5, 0x68, 0x2c, 0xfa,
4099
-	0x18, 0x5c, 0xd5, 0x56, 0x9b, 0xc9, 0x61, 0x11, 0x47, 0xc5, 0xbc, 0x97, 0xd2, 0x20, 0xe3, 0x29,
4100
-	0x3c, 0x3a, 0x85, 0x5a, 0x48, 0x45, 0xc0, 0xa3, 0x54, 0xaa, 0x1e, 0xba, 0x9a, 0x7e, 0x79, 0x13,
4101
-	0xfd, 0x64, 0x05, 0xc5, 0x79, 0x1e, 0xfa, 0x0c, 0xca, 0x42, 0x12, 0x39, 0x11, 0xfe, 0xae, 0xf6,
4102
-	0xd0, 0xd8, 0x98, 0x80, 0x46, 0xd9, 0x14, 0x2c, 0x07, 0x7d, 0x05, 0xfb, 0x63, 0x92, 0x90, 0x21,
4103
-	0xe5, 0x03, 0xeb, 0xa5, 0xac, 0xbd, 0xbc, 0x5d, 0x58, 0xba, 0x41, 0x1a, 0x47, 0xb8, 0x3e, 0xce,
4104
-	0x9b, 0xe8, 0x14, 0x80, 0x48, 0x49, 0x82, 0xef, 0xc7, 0x34, 0x91, 0x7e, 0x45, 0x7b, 0x79, 0xa7,
4105
-	0x30, 0x17, 0x2a, 0x1f, 0x33, 0x3e, 0xea, 0x2c, 0xc1, 0x38, 0x47, 0x44, 0x5f, 0x42, 0x2d, 0xa0,
4106
-	0x5c, 0x46, 0x8f, 0xa2, 0x80, 0x48, 0xea, 0x57, 0xb5, 0x9f, 0x66, 0x91, 0x9f, 0xde, 0x0a, 0x66,
4107
-	0x8b, 0xca, 0x33, 0xd1, 0xfb, 0xe0, 0x72, 0x16, 0x53, 0xdf, 0x3b, 0x72, 0xae, 0xec, 0x6f, 0x3e,
4108
-	0x16, 0xcc, 0x62, 0x8a, 0x35, 0xb2, 0xf5, 0x77, 0x09, 0x2a, 0xf7, 0x28, 0x9f, 0x46, 0xc1, 0xcb,
4109
-	0x15, 0xc8, 0xcd, 0x73, 0x02, 0x29, 0xac, 0xc5, 0x86, 0x5d, 0xd3, 0xc8, 0x31, 0x54, 0x69, 0x12,
4110
-	0xa6, 0x2c, 0x4a, 0xa4, 0x15, 0x48, 0x61, 0x21, 0xa7, 0x16, 0x83, 0x97, 0x68, 0x74, 0x0a, 0x75,
4111
-	0xa3, 0xfb, 0xc1, 0x39, 0x75, 0x1c, 0x15, 0xd1, 0xbf, 0xd3, 0x40, 0x7b, 0xac, 0x7b, 0x93, 0x9c,
4112
-	0x85, 0x4e, 0xa0, 0x9e, 0x72, 0x3a, 0x8d, 0xd8, 0x44, 0x0c, 0x74, 0x11, 0xe5, 0xe7, 0x2a, 0x02,
4113
-	0xef, 0x65, 0x2c, 0x65, 0xb5, 0x7e, 0x2d, 0x41, 0x35, 0xcb, 0x11, 0xdd, 0xb0, 0xed, 0x70, 0x36,
4114
-	0x27, 0x94, 0x61, 0xb5, 0x2b, 0xd3, 0x89, 0x1b, 0xb0, 0x9b, 0x32, 0x2e, 0x85, 0x5f, 0x3a, 0xda,
4115
-	0xd9, 0xa4, 0xf2, 0xbb, 0x8c, 0xcb, 0x1e, 0x4b, 0x1e, 0x45, 0x43, 0x6c, 0xc0, 0xe8, 0x21, 0xd4,
4116
-	0xa6, 0x11, 0x97, 0x13, 0x12, 0x0f, 0xa2, 0x54, 0xf8, 0x3b, 0x9a, 0xfb, 0xee, 0xb6, 0x90, 0xed,
4117
-	0x07, 0x06, 0xdf, 0xbf, 0xdb, 0xdd, 0x5f, 0xcc, 0x9b, 0xb0, 0x34, 0x05, 0x06, 0xeb, 0xaa, 0x9f,
4118
-	0x8a, 0x83, 0x3b, 0xe0, 0x2d, 0x77, 0xd0, 0x55, 0x80, 0xc4, 0x88, 0x7a, 0xb0, 0x14, 0x4d, 0x7d,
4119
-	0x31, 0x6f, 0x7a, 0x56, 0xea, 0xfd, 0x13, 0xec, 0x59, 0x40, 0x3f, 0x44, 0x08, 0x5c, 0x12, 0x86,
4120
-	0x5c, 0x4b, 0xc8, 0xc3, 0x7a, 0xdd, 0xfa, 0x73, 0x17, 0xdc, 0xfb, 0x44, 0x8c, 0x5e, 0xf5, 0x60,
4121
-	0x52, 0x31, 0xd7, 0x44, 0x77, 0x15, 0x40, 0x98, 0xa3, 0x54, 0xe5, 0xb8, 0xab, 0x72, 0xec, 0x01,
4122
-	0xab, 0x72, 0x2c, 0xc0, 0x94, 0x23, 0x62, 0x26, 0xb5, 0xbe, 0x5c, 0xac, 0xd7, 0xe8, 0x32, 0x54,
4123
-	0x12, 0x16, 0x6a, 0x7a, 0x59, 0xd3, 0x61, 0x31, 0x6f, 0x96, 0xd5, 0x75, 0xeb, 0x9f, 0xe0, 0xb2,
4124
-	0xda, 0xea, 0x87, 0xea, 0xa6, 0x93, 0x24, 0x61, 0x92, 0xa8, 0x31, 0x26, 0xec, 0xc4, 0x28, 0x14,
4125
-	0x56, 0x67, 0x05, 0xcb, 0x6e, 0x7a, 0x8e, 0x89, 0x1e, 0xc0, 0x6b, 0x59, 0xbe, 0x79, 0x87, 0xd5,
4126
-	0x17, 0x71, 0x88, 0xac, 0x87, 0xdc, 0x4e, 0x6e, 0xb2, 0x7a, 0x9b, 0x27, 0xab, 0xee, 0x60, 0xd1,
4127
-	0x64, 0xed, 0x42, 0x3d, 0xa4, 0x22, 0xe2, 0x34, 0xd4, 0x37, 0x90, 0xfa, 0xa0, 0x07, 0xd1, 0x5b,
4128
-	0xdb, 0x9c, 0x50, 0xbc, 0x67, 0x39, 0xda, 0x42, 0x1d, 0xa8, 0x5a, 0xdd, 0x08, 0xbf, 0xa6, 0xb5,
4129
-	0xfb, 0x9c, 0x13, 0x75, 0x49, 0x3b, 0x37, 0x41, 0xf6, 0x5e, 0x68, 0x82, 0xdc, 0x04, 0x88, 0xd9,
4130
-	0x70, 0x10, 0xf2, 0x68, 0x4a, 0xb9, 0x5f, 0xb7, 0xdf, 0xd9, 0x02, 0xee, 0x89, 0x46, 0x60, 0x2f,
4131
-	0x66, 0x43, 0xb3, 0x6c, 0xfd, 0xe4, 0xc0, 0xff, 0xd7, 0x92, 0x42, 0x1f, 0x41, 0xc5, 0xa6, 0xb5,
4132
-	0xed, 0xc1, 0x60, 0x79, 0x38, 0xc3, 0xa2, 0x43, 0xf0, 0xd4, 0x1d, 0xa1, 0x42, 0x50, 0x73, 0xfb,
4133
-	0x3d, 0xbc, 0xfa, 0x01, 0xf9, 0x50, 0x21, 0x71, 0x44, 0xd4, 0xde, 0x8e, 0xde, 0xcb, 0xcc, 0xd6,
4134
-	0xcf, 0x25, 0xa8, 0x58, 0x67, 0xaf, 0x7a, 0x9c, 0xdb, 0xb0, 0x6b, 0x37, 0xeb, 0x16, 0xec, 0x99,
4135
-	0x76, 0x5a, 0x49, 0xb8, 0xcf, 0x6c, 0x6a, 0xcd, 0xe0, 0x8d, 0x1c, 0x6e, 0x81, 0x1b, 0xa5, 0x64,
4136
-	0x6c, 0x47, 0x79, 0x61, 0xe4, 0xfe, 0xdd, 0xce, 0x9d, 0x6f, 0x53, 0xa3, 0xec, 0xea, 0x62, 0xde,
4137
-	0x74, 0xd5, 0x0f, 0x58, 0xd3, 0x5a, 0xbf, 0xed, 0x42, 0xa5, 0x17, 0x4f, 0x84, 0xa4, 0xfc, 0x55,
4138
-	0x37, 0xc4, 0x86, 0x5d, 0x6b, 0x48, 0x0f, 0x2a, 0x9c, 0x31, 0x39, 0x08, 0xc8, 0xb6, 0x5e, 0x60,
4139
-	0xc6, 0x64, 0xaf, 0xd3, 0xdd, 0x57, 0x44, 0x35, 0x48, 0x8c, 0x8d, 0xcb, 0x8a, 0xda, 0x23, 0xe8,
4140
-	0x21, 0x5c, 0xca, 0xc6, 0xef, 0x19, 0x63, 0x52, 0x48, 0x4e, 0xd2, 0xc1, 0x88, 0xce, 0xd4, 0x37,
4141
-	0x6f, 0x67, 0xd3, 0x5b, 0xe6, 0x34, 0x09, 0xf8, 0x4c, 0x37, 0xea, 0x36, 0x9d, 0xe1, 0x8b, 0xd6,
4142
-	0x41, 0x37, 0xe3, 0xdf, 0xa6, 0x33, 0x81, 0x3e, 0x87, 0x43, 0xba, 0x84, 0x29, 0x8f, 0x83, 0x98,
4143
-	0x8c, 0xd5, 0x87, 0x65, 0x10, 0xc4, 0x2c, 0x18, 0xe9, 0xd9, 0xe6, 0xe2, 0x37, 0x68, 0xde, 0xd5,
4144
-	0xd7, 0x06, 0xd1, 0x53, 0x00, 0x24, 0xc0, 0x3f, 0x8b, 0x49, 0x30, 0x8a, 0x23, 0xa1, 0x9e, 0xab,
4145
-	0xb9, 0xe7, 0x89, 0x1a, 0x4f, 0x2a, 0xb7, 0xe3, 0x2d, 0xdd, 0x6a, 0x77, 0x57, 0xdc, 0xdc, 0x63,
4146
-	0x47, 0x9c, 0x26, 0x92, 0xcf, 0xf0, 0xeb, 0x67, 0xc5, 0xbb, 0xa8, 0x0b, 0xb5, 0x49, 0xa2, 0xc2,
4147
-	0x9b, 0x1e, 0x78, 0xcf, 0xdb, 0x03, 0x30, 0x2c, 0x55, 0xf9, 0xc1, 0x14, 0x0e, 0xb7, 0x05, 0x47,
4148
-	0xff, 0x83, 0x9d, 0x11, 0x9d, 0x19, 0xfd, 0x60, 0xb5, 0x44, 0x5f, 0xc0, 0xee, 0x94, 0xc4, 0x13,
4149
-	0x6a, 0x95, 0xf3, 0x5e, 0x51, 0xbc, 0x62, 0x97, 0xd8, 0x10, 0x3f, 0x29, 0x1d, 0x3b, 0xad, 0xdf,
4150
-	0x1d, 0x28, 0xdf, 0xa3, 0x01, 0xa7, 0xf2, 0xa5, 0x2a, 0xf4, 0xf8, 0x9c, 0x42, 0x1b, 0xc5, 0x8f,
4151
-	0x17, 0x15, 0x75, 0x4d, 0xa0, 0x07, 0x50, 0x8d, 0x12, 0x49, 0x79, 0x42, 0x62, 0xad, 0xd0, 0x2a,
4152
-	0x5e, 0xda, 0x5d, 0xff, 0xc9, 0xd3, 0xc6, 0x85, 0x7f, 0x9e, 0x36, 0x2e, 0xfc, 0xb8, 0x68, 0x38,
4153
-	0x4f, 0x16, 0x0d, 0xe7, 0xaf, 0x45, 0xc3, 0xf9, 0x77, 0xd1, 0x70, 0xce, 0xca, 0xfa, 0x6f, 0xc8,
4154
-	0x87, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xf1, 0xbb, 0xa8, 0xb4, 0xa0, 0x0d, 0x00, 0x00,
4080
+	// 1333 bytes of a gzipped FileDescriptorProto
4081
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x57, 0xc1, 0x8f, 0x1b, 0xb5,
4082
+	0x17, 0xde, 0x49, 0x66, 0x93, 0xcc, 0xcb, 0x66, 0xf5, 0xfb, 0xb9, 0xa5, 0x4c, 0x97, 0x25, 0x59,
4083
+	0xb6, 0x02, 0x55, 0xa8, 0xca, 0x42, 0x29, 0x68, 0x5b, 0x28, 0x90, 0x64, 0x23, 0x88, 0x4a, 0x69,
4084
+	0xe5, 0x96, 0xf6, 0x18, 0x79, 0x67, 0xdc, 0x30, 0x64, 0x32, 0x1e, 0xd9, 0x4e, 0x4a, 0x6e, 0x88,
4085
+	0x23, 0x47, 0x84, 0xc4, 0x0d, 0x89, 0x0b, 0x67, 0xae, 0xfc, 0x07, 0x7b, 0xe4, 0xc8, 0x69, 0x45,
4086
+	0x73, 0xe3, 0xc2, 0xdf, 0x80, 0xec, 0xf1, 0x64, 0x67, 0x9b, 0xc9, 0x6e, 0x8b, 0xaa, 0x15, 0xa7,
4087
+	0xd8, 0xe3, 0xef, 0x7b, 0x7e, 0xcf, 0xfe, 0xfc, 0xd9, 0x81, 0x1a, 0xdb, 0xff, 0x8a, 0x7a, 0x52,
4088
+	0x34, 0x63, 0xce, 0x24, 0x43, 0xc8, 0x67, 0xde, 0x90, 0xf2, 0xa6, 0x78, 0x4c, 0xf8, 0x68, 0x18,
4089
+	0xc8, 0xe6, 0xe4, 0xed, 0x8d, 0xaa, 0x9c, 0xc6, 0xd4, 0x00, 0x36, 0xaa, 0x22, 0xa6, 0x5e, 0xda,
4090
+	0x69, 0x0c, 0x18, 0x1b, 0x84, 0x74, 0x47, 0xf7, 0xf6, 0xc7, 0x8f, 0x76, 0x64, 0x30, 0xa2, 0x42,
4091
+	0x92, 0x51, 0x6c, 0x00, 0xe7, 0x07, 0x6c, 0xc0, 0x74, 0x73, 0x47, 0xb5, 0xcc, 0xd7, 0x8b, 0x4f,
4092
+	0xd3, 0x48, 0x34, 0x35, 0x43, 0xe7, 0xe2, 0x70, 0x3c, 0x08, 0xa2, 0x9d, 0xe4, 0x27, 0xf9, 0xb8,
4093
+	0xfd, 0x9b, 0x05, 0xf6, 0x6d, 0x2a, 0x09, 0x7a, 0x1f, 0xca, 0x13, 0xca, 0x45, 0xc0, 0x22, 0xd7,
4094
+	0xda, 0xb2, 0x2e, 0x57, 0xaf, 0xbe, 0xd2, 0x5c, 0xcc, 0xb7, 0xf9, 0x20, 0x81, 0xb4, 0xed, 0x83,
4095
+	0xc3, 0xc6, 0x0a, 0x4e, 0x19, 0xe8, 0x3a, 0x80, 0xc7, 0x29, 0x91, 0xd4, 0xef, 0x13, 0xe9, 0x16,
4096
+	0x34, 0x7f, 0xa3, 0x99, 0xa4, 0xd2, 0x4c, 0x53, 0x69, 0xde, 0x4f, 0x2b, 0xc0, 0x8e, 0x41, 0xb7,
4097
+	0xa4, 0xa2, 0x8e, 0x63, 0x3f, 0xa5, 0x16, 0x4f, 0xa7, 0x1a, 0x74, 0x4b, 0x6e, 0xff, 0x6c, 0x83,
4098
+	0xfd, 0x39, 0xf3, 0x29, 0xba, 0x00, 0x85, 0xc0, 0xd7, 0x69, 0x3b, 0xed, 0xd2, 0xec, 0xb0, 0x51,
4099
+	0xe8, 0xed, 0xe1, 0x42, 0xe0, 0xa3, 0xab, 0x60, 0x8f, 0xa8, 0x24, 0x26, 0x21, 0x37, 0xaf, 0x20,
4100
+	0x55, 0xbb, 0xa9, 0x46, 0x63, 0xd1, 0x7b, 0x60, 0xab, 0x6d, 0x30, 0x99, 0x6c, 0xe6, 0x71, 0xd4,
4101
+	0x9c, 0xf7, 0x62, 0xea, 0xa5, 0x3c, 0x85, 0x47, 0x5d, 0xa8, 0xfa, 0x54, 0x78, 0x3c, 0x88, 0xa5,
4102
+	0x5a, 0x43, 0x5b, 0xd3, 0x2f, 0x2d, 0xa3, 0xef, 0x1d, 0x41, 0x71, 0x96, 0x87, 0x3e, 0x80, 0x92,
4103
+	0x90, 0x44, 0x8e, 0x85, 0xbb, 0xaa, 0x23, 0xd4, 0x97, 0x26, 0xa0, 0x51, 0x26, 0x05, 0xc3, 0x41,
4104
+	0x9f, 0xc2, 0xfa, 0x88, 0x44, 0x64, 0x40, 0x79, 0xdf, 0x44, 0x29, 0xe9, 0x28, 0xaf, 0xe5, 0x96,
4105
+	0x9e, 0x20, 0x93, 0x40, 0xb8, 0x36, 0xca, 0x76, 0x51, 0x17, 0x80, 0x48, 0x49, 0xbc, 0x2f, 0x47,
4106
+	0x34, 0x92, 0x6e, 0x59, 0x47, 0x79, 0x3d, 0x37, 0x17, 0x2a, 0x1f, 0x33, 0x3e, 0x6c, 0xcd, 0xc1,
4107
+	0x38, 0x43, 0x44, 0x9f, 0x40, 0xd5, 0xa3, 0x5c, 0x06, 0x8f, 0x02, 0x8f, 0x48, 0xea, 0x56, 0x74,
4108
+	0x9c, 0x46, 0x5e, 0x9c, 0xce, 0x11, 0xcc, 0x14, 0x95, 0x65, 0xa2, 0xb7, 0xc0, 0xe6, 0x2c, 0xa4,
4109
+	0xae, 0xb3, 0x65, 0x5d, 0x5e, 0x5f, 0xbe, 0x2d, 0x98, 0x85, 0x14, 0x6b, 0xe4, 0x0d, 0xfb, 0xbb,
4110
+	0x1f, 0xb7, 0x57, 0xb6, 0xff, 0x2e, 0x42, 0xf9, 0x1e, 0xe5, 0x93, 0xc0, 0x7b, 0xb1, 0x32, 0xb9,
4111
+	0x7e, 0x4c, 0x26, 0xb9, 0x15, 0x99, 0x69, 0x17, 0x94, 0xb2, 0x0b, 0x15, 0x1a, 0xf9, 0x31, 0x0b,
4112
+	0x22, 0x69, 0x64, 0x92, 0x5b, 0x4e, 0xd7, 0x60, 0xf0, 0x1c, 0x8d, 0xba, 0x50, 0x4b, 0xd4, 0xdf,
4113
+	0x3f, 0xa6, 0x91, 0xad, 0x3c, 0xfa, 0x17, 0x1a, 0x68, 0x36, 0x77, 0x6d, 0x9c, 0xe9, 0xa1, 0x3d,
4114
+	0xa8, 0xc5, 0x9c, 0x4e, 0x02, 0x36, 0x16, 0x7d, 0x5d, 0x44, 0xe9, 0x99, 0x8a, 0xc0, 0x6b, 0x29,
4115
+	0x4b, 0xf5, 0xd0, 0x87, 0xb0, 0xa6, 0xc8, 0xfd, 0xd4, 0x35, 0xe0, 0x54, 0xd7, 0xc0, 0xda, 0xe0,
4116
+	0x4c, 0x07, 0xdd, 0x81, 0x97, 0x8e, 0x65, 0x31, 0x0f, 0x54, 0x3d, 0x3d, 0xd0, 0xb9, 0x6c, 0x26,
4117
+	0xe6, 0xa3, 0xd9, 0xf0, 0x9f, 0x0a, 0x50, 0x49, 0x97, 0x0e, 0x5d, 0x33, 0xbb, 0x64, 0x2d, 0x5f,
4118
+	0xa7, 0x14, 0xab, 0x2b, 0x4c, 0x36, 0xe8, 0x1a, 0xac, 0xc6, 0x8c, 0x4b, 0xe1, 0x16, 0xb6, 0x8a,
4119
+	0xcb, 0x8e, 0xe0, 0x5d, 0xc6, 0x65, 0x87, 0x45, 0x8f, 0x82, 0x01, 0x4e, 0xc0, 0xe8, 0x21, 0x54,
4120
+	0x27, 0x01, 0x97, 0x63, 0x12, 0xf6, 0x83, 0x58, 0xb8, 0x45, 0xcd, 0x7d, 0xe3, 0xa4, 0x29, 0x9b,
4121
+	0x0f, 0x12, 0x7c, 0xef, 0x6e, 0x7b, 0x7d, 0x76, 0xd8, 0x80, 0x79, 0x57, 0x60, 0x30, 0xa1, 0x7a,
4122
+	0xb1, 0xd8, 0xb8, 0x0d, 0xce, 0x7c, 0x04, 0x5d, 0x01, 0x88, 0x92, 0x13, 0xd7, 0x9f, 0x6b, 0xb9,
4123
+	0x36, 0x3b, 0x6c, 0x38, 0xe6, 0x1c, 0xf6, 0xf6, 0xb0, 0x63, 0x00, 0x3d, 0x1f, 0x21, 0xb0, 0x89,
4124
+	0xef, 0x73, 0xad, 0x6c, 0x07, 0xeb, 0xf6, 0xf6, 0xf7, 0x25, 0xb0, 0xef, 0x13, 0x31, 0x3c, 0x6b,
4125
+	0xd7, 0x54, 0x73, 0x2e, 0x9c, 0x85, 0x2b, 0x00, 0x22, 0x51, 0x98, 0x2a, 0xc7, 0x3e, 0x2a, 0xc7,
4126
+	0xe8, 0x4e, 0x95, 0x63, 0x00, 0x49, 0x39, 0x22, 0x64, 0x52, 0xcb, 0xde, 0xc6, 0xba, 0x8d, 0x2e,
4127
+	0x41, 0x39, 0x62, 0xbe, 0xa6, 0x97, 0x34, 0x1d, 0x66, 0x87, 0x8d, 0x92, 0xf2, 0x82, 0xde, 0x1e,
4128
+	0x2e, 0xa9, 0xa1, 0x9e, 0xaf, 0x6c, 0x88, 0x44, 0x11, 0x93, 0x44, 0x79, 0xac, 0x30, 0x76, 0x96,
4129
+	0xab, 0xf7, 0xd6, 0x11, 0x2c, 0xb5, 0xa1, 0x0c, 0x13, 0x3d, 0x80, 0x73, 0x69, 0xbe, 0xd9, 0x80,
4130
+	0x95, 0xe7, 0x09, 0x88, 0x4c, 0x84, 0xcc, 0x48, 0xc6, 0xf6, 0x9d, 0xe5, 0xb6, 0xaf, 0x57, 0x30,
4131
+	0xcf, 0xf6, 0xdb, 0x50, 0xf3, 0xa9, 0x08, 0x38, 0xf5, 0xb5, 0x31, 0x50, 0x7d, 0x16, 0xd7, 0xaf,
4132
+	0xbe, 0x7a, 0x52, 0x10, 0x8a, 0xd7, 0x0c, 0x47, 0xf7, 0x50, 0x0b, 0x2a, 0x46, 0x37, 0xc2, 0xad,
4133
+	0x6a, 0xed, 0x3e, 0xa3, 0xdd, 0xcf, 0x69, 0xc7, 0x8c, 0x6d, 0xed, 0xb9, 0x8c, 0xed, 0x3a, 0x40,
4134
+	0xc8, 0x06, 0x7d, 0x9f, 0x07, 0x13, 0xca, 0xdd, 0x9a, 0x79, 0x04, 0xe4, 0x70, 0xf7, 0x34, 0x02,
4135
+	0x3b, 0x21, 0x1b, 0x24, 0xcd, 0x05, 0x1b, 0x5a, 0x7f, 0x3e, 0x1b, 0x32, 0xae, 0xf1, 0xad, 0x05,
4136
+	0xff, 0x5f, 0x28, 0x0d, 0xbd, 0x0b, 0x65, 0x53, 0xdc, 0x49, 0x6f, 0x22, 0xc3, 0xc3, 0x29, 0x16,
4137
+	0x6d, 0x82, 0xa3, 0x4e, 0x1a, 0x15, 0x82, 0x26, 0x1e, 0xe2, 0xe0, 0xa3, 0x0f, 0xc8, 0x85, 0x32,
4138
+	0x09, 0x03, 0xa2, 0xc6, 0x8a, 0x7a, 0x2c, 0xed, 0x6e, 0xff, 0x50, 0x80, 0xb2, 0x09, 0x76, 0xd6,
4139
+	0x77, 0x95, 0x99, 0x76, 0xe1, 0x7c, 0xde, 0x84, 0xb5, 0x64, 0x53, 0x8c, 0xb0, 0xec, 0x53, 0xb7,
4140
+	0xa6, 0x9a, 0xe0, 0x13, 0x51, 0xdd, 0x04, 0x3b, 0x88, 0xc9, 0xc8, 0xdc, 0x53, 0xb9, 0x33, 0xf7,
4141
+	0xee, 0xb6, 0x6e, 0xdf, 0x89, 0x93, 0xf3, 0x51, 0x99, 0x1d, 0x36, 0x6c, 0xf5, 0x01, 0x6b, 0x9a,
4142
+	0xd9, 0x9b, 0x5f, 0x56, 0xa1, 0xdc, 0x09, 0xc7, 0x42, 0x52, 0x7e, 0xd6, 0xcb, 0x62, 0xa6, 0x5d,
4143
+	0x58, 0x96, 0x0e, 0x94, 0x39, 0x63, 0xb2, 0xef, 0x91, 0x93, 0x56, 0x04, 0x33, 0x26, 0x3b, 0xad,
4144
+	0xf6, 0xba, 0x22, 0x2a, 0x53, 0x4a, 0xfa, 0xb8, 0xa4, 0xa8, 0x1d, 0x82, 0x1e, 0xc2, 0x85, 0xd4,
4145
+	0xca, 0xf7, 0x19, 0x93, 0x42, 0x72, 0x12, 0xf7, 0x87, 0x74, 0xaa, 0xae, 0xf5, 0xe2, 0xb2, 0x47,
4146
+	0x5b, 0x37, 0xf2, 0xf8, 0x54, 0x2f, 0xd7, 0x2d, 0x3a, 0xc5, 0xe7, 0x4d, 0x80, 0x76, 0xca, 0xbf,
4147
+	0x45, 0xa7, 0x02, 0x7d, 0x04, 0x9b, 0x74, 0x0e, 0x53, 0x11, 0xfb, 0x21, 0x19, 0xa9, 0x4b, 0xaa,
4148
+	0xef, 0x85, 0xcc, 0x1b, 0x6a, 0x9f, 0xb4, 0xf1, 0x45, 0x9a, 0x0d, 0xf5, 0x59, 0x82, 0xe8, 0x28,
4149
+	0x00, 0x12, 0xe0, 0xee, 0x87, 0xc4, 0x1b, 0x86, 0x81, 0x50, 0xef, 0xf2, 0xcc, 0x3b, 0x4c, 0x59,
4150
+	0x9d, 0xca, 0x6d, 0xf7, 0x84, 0xd5, 0x6a, 0xb6, 0x8f, 0xb8, 0x99, 0x57, 0x9d, 0xe8, 0x46, 0x92,
4151
+	0x4f, 0xf1, 0xcb, 0xfb, 0xf9, 0xa3, 0xa8, 0x0d, 0xd5, 0x71, 0xa4, 0xa6, 0x4f, 0xd6, 0xc0, 0x79,
4152
+	0xd6, 0x35, 0x80, 0x84, 0xa5, 0x2a, 0xdf, 0x98, 0xc0, 0xe6, 0x49, 0x93, 0xa3, 0xff, 0x41, 0x71,
4153
+	0x48, 0xa7, 0x89, 0x7e, 0xb0, 0x6a, 0xa2, 0x8f, 0x61, 0x75, 0x42, 0xc2, 0x31, 0x35, 0xca, 0x79,
4154
+	0x33, 0x6f, 0xbe, 0xfc, 0x90, 0x38, 0x21, 0xde, 0x28, 0xec, 0x5a, 0x46, 0xa8, 0xbf, 0x5a, 0x50,
4155
+	0xba, 0x47, 0x3d, 0x4e, 0xe5, 0x0b, 0xd5, 0xe9, 0xee, 0x31, 0x9d, 0xd6, 0xf3, 0x5f, 0x69, 0x6a,
4156
+	0xd6, 0x05, 0x99, 0x6e, 0x40, 0x25, 0x88, 0x24, 0xe5, 0x11, 0x09, 0xb5, 0x4e, 0x2b, 0x78, 0xde,
4157
+	0x37, 0x29, 0xff, 0x65, 0x41, 0x05, 0x53, 0xc1, 0xc6, 0xfc, 0x05, 0xbf, 0x8f, 0x9f, 0xba, 0x71,
4158
+	0x8b, 0xff, 0xfa, 0xc6, 0x45, 0x60, 0x0f, 0x83, 0xc8, 0xbc, 0x0d, 0xb0, 0x6e, 0xa3, 0x26, 0x94,
4159
+	0x63, 0x32, 0x0d, 0x19, 0xf1, 0x8d, 0xb3, 0x9c, 0x5f, 0xf8, 0xc3, 0xd8, 0x8a, 0xa6, 0x38, 0x05,
4160
+	0x99, 0x5a, 0x0f, 0x2c, 0x70, 0xba, 0x5f, 0x4b, 0x1a, 0xe9, 0xe7, 0xe7, 0x7f, 0xb2, 0xd8, 0xad,
4161
+	0xc5, 0x3f, 0x91, 0xce, 0xb1, 0xff, 0x87, 0x49, 0x29, 0x6d, 0xf7, 0xe0, 0x49, 0x7d, 0xe5, 0x8f,
4162
+	0x27, 0xf5, 0x95, 0x6f, 0x66, 0x75, 0xeb, 0x60, 0x56, 0xb7, 0x7e, 0x9f, 0xd5, 0xad, 0x3f, 0x67,
4163
+	0x75, 0x6b, 0xbf, 0xa4, 0x57, 0xe0, 0x9d, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x6e, 0x08,
4164
+	0x2c, 0x7c, 0x10, 0x00, 0x00,
4155 4165
 }
... ...
@@ -6,6 +6,8 @@ import "types.proto";
6 6
 import "specs.proto";
7 7
 import "google/protobuf/timestamp.proto";
8 8
 import "gogoproto/gogo.proto";
9
+import "google/protobuf/any.proto";
10
+import "plugin/plugin.proto";
9 11
 
10 12
 // This file contains definitions for all first-class objects in the cluster
11 13
 // API. Such types typically have a corresponding specification, with the
... ...
@@ -24,6 +26,8 @@ message Meta {
24 24
 
25 25
 // Node provides the internal node state as seen by the cluster.
26 26
 message Node {
27
+	option (docker.protobuf.plugin.store_object) = { };
28
+
27 29
 	// ID specifies the identity of the node.
28 30
 	string id = 1;
29 31
 
... ...
@@ -63,16 +67,26 @@ message Node {
63 63
 }
64 64
 
65 65
 message Service {
66
+	option (docker.protobuf.plugin.store_object) = { };
67
+
66 68
 	string id = 1;
67 69
 
68 70
 	Meta meta = 2 [(gogoproto.nullable) = false];
69 71
 
70 72
 	ServiceSpec spec = 3 [(gogoproto.nullable) = false];
71 73
 
74
+	// SpecVersion versions Spec, to identify changes in the spec. Note that
75
+	// this is not directly comparable to the service's Version.
76
+	Version spec_version = 10;
77
+
72 78
 	// PreviousSpec is the previous service spec that was in place before
73 79
 	// "Spec".
74 80
 	ServiceSpec previous_spec = 6;
75 81
 
82
+	// PreviousSpecVersion versions PreviousSpec. Note that this is not
83
+	// directly comparable to the service's Version.
84
+	Version previous_spec_version = 11;
85
+
76 86
 	// Runtime state of service endpoint. This may be different
77 87
 	// from the spec version because the user may not have entered
78 88
 	// the optional fields like node_port or virtual_ip and it
... ...
@@ -123,6 +137,8 @@ message Endpoint {
123 123
 // immutable and idempotent. Once it is dispatched to a node, it will not be
124 124
 // dispatched to another node.
125 125
 message Task {
126
+	option (docker.protobuf.plugin.store_object) = { };
127
+
126 128
 	string id = 1;
127 129
 
128 130
 	Meta meta = 2 [(gogoproto.nullable) = false];
... ...
@@ -131,6 +147,11 @@ message Task {
131 131
 	// The system will honor this and will *never* modify it.
132 132
 	TaskSpec spec = 3 [(gogoproto.nullable) = false];
133 133
 
134
+	// SpecVersion is copied from Service, to identify which version of the
135
+	// spec this task has. Note that this is not directly comparable to the
136
+	// service's Version.
137
+	Version spec_version = 14;
138
+
134 139
 	// ServiceID indicates the service under which this task is orchestrated. This
135 140
 	// should almost always be set.
136 141
 	string service_id = 4;
... ...
@@ -204,6 +225,8 @@ message NetworkAttachment {
204 204
 }
205 205
 
206 206
 message Network {
207
+	option (docker.protobuf.plugin.store_object) = { };
208
+
207 209
 	string id = 1;
208 210
 
209 211
 	Meta meta = 2 [(gogoproto.nullable) = false];
... ...
@@ -220,6 +243,8 @@ message Network {
220 220
 
221 221
 // Cluster provides global cluster settings.
222 222
 message Cluster {
223
+	option (docker.protobuf.plugin.store_object) = { };
224
+
223 225
 	string id = 1;
224 226
 
225 227
 	Meta meta = 2 [(gogoproto.nullable) = false];
... ...
@@ -256,6 +281,8 @@ message Cluster {
256 256
 // information that is generated from the secret data in the `spec`, such as
257 257
 // the digest and size of the secret data.
258 258
 message Secret {
259
+	option (docker.protobuf.plugin.store_object) = { };
260
+
259 261
 	string id = 1;
260 262
 
261 263
 	Meta meta = 2 [(gogoproto.nullable) = false];
... ...
@@ -267,3 +294,54 @@ message Secret {
267 267
 	// Whether the secret is an internal secret (not set by a user) or not.
268 268
 	bool internal = 4;
269 269
 }
270
+
271
+// Resource is a top-level object with externally defined content and indexing.
272
+// SwarmKit can serve as a store for these objects without understanding their
273
+// meanings.
274
+message Resource {
275
+	option (docker.protobuf.plugin.store_object) = { };
276
+
277
+	string id = 1 [(gogoproto.customname) = "ID"];
278
+
279
+	Meta meta = 2 [(gogoproto.nullable) = false];
280
+
281
+	Annotations annotations = 3 [(gogoproto.nullable) = false];
282
+
283
+	// Kind identifies this class of object. It is essentially a namespace
284
+	// to keep IDs or indices from colliding between unrelated Resource
285
+	// objects. This must correspond to the name of an Extension.
286
+	string kind = 4;
287
+
288
+	// Payload bytes. This data is not interpreted in any way by SwarmKit.
289
+	// By convention, it should be a marshalled protocol buffers message.
290
+	google.protobuf.Any payload = 5;
291
+}
292
+
293
+// Extension declares a type of "resource" object. This message provides some
294
+// metadata about the objects.
295
+message Extension {
296
+	option (docker.protobuf.plugin.store_object) = { };
297
+
298
+	string id = 1 [(gogoproto.customname) = "ID"];
299
+
300
+	Meta meta = 2 [(gogoproto.nullable) = false];
301
+
302
+	Annotations annotations = 3 [(gogoproto.nullable) = false];
303
+
304
+	string description = 4;
305
+
306
+	// TODO(aaronl): Add optional indexing capabilities. It would be
307
+	// extremely useful be able to automatically introspect protobuf, json,
308
+	// etc. objects and automatically index them based on a schema and field
309
+	// paths defined here.
310
+	//
311
+	//oneof Schema {
312
+	//	google.protobuf.Descriptor protobuf = 1;
313
+	//	bytes json = 2;
314
+	//}
315
+	//
316
+	//Schema schema = 5;
317
+	//
318
+	// // Indices, with values expressed as Go templates.
319
+	//repeated IndexEntry index_templates = 6;
320
+}
... ...
@@ -155,8 +155,8 @@ func (*ResolveAddressResponse) Descriptor() ([]byte, []int) { return fileDescrip
155 155
 // over the raft backend with a request ID to track when the
156 156
 // action is effectively applied
157 157
 type InternalRaftRequest struct {
158
-	ID     uint64         `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
159
-	Action []*StoreAction `protobuf:"bytes,2,rep,name=action" json:"action,omitempty"`
158
+	ID     uint64        `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
159
+	Action []StoreAction `protobuf:"bytes,2,rep,name=action" json:"action"`
160 160
 }
161 161
 
162 162
 func (m *InternalRaftRequest) Reset()                    { *m = InternalRaftRequest{} }
... ...
@@ -173,6 +173,8 @@ type StoreAction struct {
173 173
 	//	*StoreAction_Network
174 174
 	//	*StoreAction_Cluster
175 175
 	//	*StoreAction_Secret
176
+	//	*StoreAction_Resource
177
+	//	*StoreAction_Extension
176 178
 	Target isStoreAction_Target `protobuf_oneof:"target"`
177 179
 }
178 180
 
... ...
@@ -204,13 +206,21 @@ type StoreAction_Cluster struct {
204 204
 type StoreAction_Secret struct {
205 205
 	Secret *Secret `protobuf:"bytes,7,opt,name=secret,oneof"`
206 206
 }
207
+type StoreAction_Resource struct {
208
+	Resource *Resource `protobuf:"bytes,8,opt,name=resource,oneof"`
209
+}
210
+type StoreAction_Extension struct {
211
+	Extension *Extension `protobuf:"bytes,9,opt,name=extension,oneof"`
212
+}
207 213
 
208
-func (*StoreAction_Node) isStoreAction_Target()    {}
209
-func (*StoreAction_Service) isStoreAction_Target() {}
210
-func (*StoreAction_Task) isStoreAction_Target()    {}
211
-func (*StoreAction_Network) isStoreAction_Target() {}
212
-func (*StoreAction_Cluster) isStoreAction_Target() {}
213
-func (*StoreAction_Secret) isStoreAction_Target()  {}
214
+func (*StoreAction_Node) isStoreAction_Target()      {}
215
+func (*StoreAction_Service) isStoreAction_Target()   {}
216
+func (*StoreAction_Task) isStoreAction_Target()      {}
217
+func (*StoreAction_Network) isStoreAction_Target()   {}
218
+func (*StoreAction_Cluster) isStoreAction_Target()   {}
219
+func (*StoreAction_Secret) isStoreAction_Target()    {}
220
+func (*StoreAction_Resource) isStoreAction_Target()  {}
221
+func (*StoreAction_Extension) isStoreAction_Target() {}
214 222
 
215 223
 func (m *StoreAction) GetTarget() isStoreAction_Target {
216 224
 	if m != nil {
... ...
@@ -261,6 +271,20 @@ func (m *StoreAction) GetSecret() *Secret {
261 261
 	return nil
262 262
 }
263 263
 
264
+func (m *StoreAction) GetResource() *Resource {
265
+	if x, ok := m.GetTarget().(*StoreAction_Resource); ok {
266
+		return x.Resource
267
+	}
268
+	return nil
269
+}
270
+
271
+func (m *StoreAction) GetExtension() *Extension {
272
+	if x, ok := m.GetTarget().(*StoreAction_Extension); ok {
273
+		return x.Extension
274
+	}
275
+	return nil
276
+}
277
+
264 278
 // XXX_OneofFuncs is for the internal use of the proto package.
265 279
 func (*StoreAction) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
266 280
 	return _StoreAction_OneofMarshaler, _StoreAction_OneofUnmarshaler, _StoreAction_OneofSizer, []interface{}{
... ...
@@ -270,6 +294,8 @@ func (*StoreAction) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) e
270 270
 		(*StoreAction_Network)(nil),
271 271
 		(*StoreAction_Cluster)(nil),
272 272
 		(*StoreAction_Secret)(nil),
273
+		(*StoreAction_Resource)(nil),
274
+		(*StoreAction_Extension)(nil),
273 275
 	}
274 276
 }
275 277
 
... ...
@@ -307,6 +333,16 @@ func _StoreAction_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
307 307
 		if err := b.EncodeMessage(x.Secret); err != nil {
308 308
 			return err
309 309
 		}
310
+	case *StoreAction_Resource:
311
+		_ = b.EncodeVarint(8<<3 | proto.WireBytes)
312
+		if err := b.EncodeMessage(x.Resource); err != nil {
313
+			return err
314
+		}
315
+	case *StoreAction_Extension:
316
+		_ = b.EncodeVarint(9<<3 | proto.WireBytes)
317
+		if err := b.EncodeMessage(x.Extension); err != nil {
318
+			return err
319
+		}
310 320
 	case nil:
311 321
 	default:
312 322
 		return fmt.Errorf("StoreAction.Target has unexpected type %T", x)
... ...
@@ -365,6 +401,22 @@ func _StoreAction_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Bu
365 365
 		err := b.DecodeMessage(msg)
366 366
 		m.Target = &StoreAction_Secret{msg}
367 367
 		return true, err
368
+	case 8: // target.resource
369
+		if wire != proto.WireBytes {
370
+			return true, proto.ErrInternalBadWireType
371
+		}
372
+		msg := new(Resource)
373
+		err := b.DecodeMessage(msg)
374
+		m.Target = &StoreAction_Resource{msg}
375
+		return true, err
376
+	case 9: // target.extension
377
+		if wire != proto.WireBytes {
378
+			return true, proto.ErrInternalBadWireType
379
+		}
380
+		msg := new(Extension)
381
+		err := b.DecodeMessage(msg)
382
+		m.Target = &StoreAction_Extension{msg}
383
+		return true, err
368 384
 	default:
369 385
 		return false, nil
370 386
 	}
... ...
@@ -404,6 +456,16 @@ func _StoreAction_OneofSizer(msg proto.Message) (n int) {
404 404
 		n += proto.SizeVarint(7<<3 | proto.WireBytes)
405 405
 		n += proto.SizeVarint(uint64(s))
406 406
 		n += s
407
+	case *StoreAction_Resource:
408
+		s := proto.Size(x.Resource)
409
+		n += proto.SizeVarint(8<<3 | proto.WireBytes)
410
+		n += proto.SizeVarint(uint64(s))
411
+		n += s
412
+	case *StoreAction_Extension:
413
+		s := proto.Size(x.Extension)
414
+		n += proto.SizeVarint(9<<3 | proto.WireBytes)
415
+		n += proto.SizeVarint(uint64(s))
416
+		n += s
407 417
 	case nil:
408 418
 	default:
409 419
 		panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
... ...
@@ -624,10 +686,9 @@ func (m *InternalRaftRequest) CopyFrom(src interface{}) {
624 624
 	o := src.(*InternalRaftRequest)
625 625
 	*m = *o
626 626
 	if o.Action != nil {
627
-		m.Action = make([]*StoreAction, len(o.Action))
627
+		m.Action = make([]StoreAction, len(o.Action))
628 628
 		for i := range m.Action {
629
-			m.Action[i] = &StoreAction{}
630
-			github_com_docker_swarmkit_api_deepcopy.Copy(m.Action[i], o.Action[i])
629
+			github_com_docker_swarmkit_api_deepcopy.Copy(&m.Action[i], &o.Action[i])
631 630
 		}
632 631
 	}
633 632
 
... ...
@@ -684,6 +745,18 @@ func (m *StoreAction) CopyFrom(src interface{}) {
684 684
 			}
685 685
 			github_com_docker_swarmkit_api_deepcopy.Copy(v.Secret, o.GetSecret())
686 686
 			m.Target = &v
687
+		case *StoreAction_Resource:
688
+			v := StoreAction_Resource{
689
+				Resource: &Resource{},
690
+			}
691
+			github_com_docker_swarmkit_api_deepcopy.Copy(v.Resource, o.GetResource())
692
+			m.Target = &v
693
+		case *StoreAction_Extension:
694
+			v := StoreAction_Extension{
695
+				Extension: &Extension{},
696
+			}
697
+			github_com_docker_swarmkit_api_deepcopy.Copy(v.Extension, o.GetExtension())
698
+			m.Target = &v
687 699
 		}
688 700
 	}
689 701
 
... ...
@@ -1308,6 +1381,34 @@ func (m *StoreAction_Secret) MarshalTo(dAtA []byte) (int, error) {
1308 1308
 	}
1309 1309
 	return i, nil
1310 1310
 }
1311
+func (m *StoreAction_Resource) MarshalTo(dAtA []byte) (int, error) {
1312
+	i := 0
1313
+	if m.Resource != nil {
1314
+		dAtA[i] = 0x42
1315
+		i++
1316
+		i = encodeVarintRaft(dAtA, i, uint64(m.Resource.Size()))
1317
+		n13, err := m.Resource.MarshalTo(dAtA[i:])
1318
+		if err != nil {
1319
+			return 0, err
1320
+		}
1321
+		i += n13
1322
+	}
1323
+	return i, nil
1324
+}
1325
+func (m *StoreAction_Extension) MarshalTo(dAtA []byte) (int, error) {
1326
+	i := 0
1327
+	if m.Extension != nil {
1328
+		dAtA[i] = 0x4a
1329
+		i++
1330
+		i = encodeVarintRaft(dAtA, i, uint64(m.Extension.Size()))
1331
+		n14, err := m.Extension.MarshalTo(dAtA[i:])
1332
+		if err != nil {
1333
+			return 0, err
1334
+		}
1335
+		i += n14
1336
+	}
1337
+	return i, nil
1338
+}
1311 1339
 func encodeFixed64Raft(dAtA []byte, offset int, v uint64) int {
1312 1340
 	dAtA[offset] = uint8(v)
1313 1341
 	dAtA[offset+1] = uint8(v >> 8)
... ...
@@ -1803,6 +1904,24 @@ func (m *StoreAction_Secret) Size() (n int) {
1803 1803
 	}
1804 1804
 	return n
1805 1805
 }
1806
+func (m *StoreAction_Resource) Size() (n int) {
1807
+	var l int
1808
+	_ = l
1809
+	if m.Resource != nil {
1810
+		l = m.Resource.Size()
1811
+		n += 1 + l + sovRaft(uint64(l))
1812
+	}
1813
+	return n
1814
+}
1815
+func (m *StoreAction_Extension) Size() (n int) {
1816
+	var l int
1817
+	_ = l
1818
+	if m.Extension != nil {
1819
+		l = m.Extension.Size()
1820
+		n += 1 + l + sovRaft(uint64(l))
1821
+	}
1822
+	return n
1823
+}
1806 1824
 
1807 1825
 func sovRaft(x uint64) (n int) {
1808 1826
 	for {
... ...
@@ -1916,7 +2035,7 @@ func (this *InternalRaftRequest) String() string {
1916 1916
 	}
1917 1917
 	s := strings.Join([]string{`&InternalRaftRequest{`,
1918 1918
 		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
1919
-		`Action:` + strings.Replace(fmt.Sprintf("%v", this.Action), "StoreAction", "StoreAction", 1) + `,`,
1919
+		`Action:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Action), "StoreAction", "StoreAction", 1), `&`, ``, 1) + `,`,
1920 1920
 		`}`,
1921 1921
 	}, "")
1922 1922
 	return s
... ...
@@ -1992,6 +2111,26 @@ func (this *StoreAction_Secret) String() string {
1992 1992
 	}, "")
1993 1993
 	return s
1994 1994
 }
1995
+func (this *StoreAction_Resource) String() string {
1996
+	if this == nil {
1997
+		return "nil"
1998
+	}
1999
+	s := strings.Join([]string{`&StoreAction_Resource{`,
2000
+		`Resource:` + strings.Replace(fmt.Sprintf("%v", this.Resource), "Resource", "Resource", 1) + `,`,
2001
+		`}`,
2002
+	}, "")
2003
+	return s
2004
+}
2005
+func (this *StoreAction_Extension) String() string {
2006
+	if this == nil {
2007
+		return "nil"
2008
+	}
2009
+	s := strings.Join([]string{`&StoreAction_Extension{`,
2010
+		`Extension:` + strings.Replace(fmt.Sprintf("%v", this.Extension), "Extension", "Extension", 1) + `,`,
2011
+		`}`,
2012
+	}, "")
2013
+	return s
2014
+}
1995 2015
 func valueToStringRaft(v interface{}) string {
1996 2016
 	rv := reflect.ValueOf(v)
1997 2017
 	if rv.IsNil() {
... ...
@@ -2886,7 +3025,7 @@ func (m *InternalRaftRequest) Unmarshal(dAtA []byte) error {
2886 2886
 			if postIndex > l {
2887 2887
 				return io.ErrUnexpectedEOF
2888 2888
 			}
2889
-			m.Action = append(m.Action, &StoreAction{})
2889
+			m.Action = append(m.Action, StoreAction{})
2890 2890
 			if err := m.Action[len(m.Action)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
2891 2891
 				return err
2892 2892
 			}
... ...
@@ -3152,6 +3291,70 @@ func (m *StoreAction) Unmarshal(dAtA []byte) error {
3152 3152
 			}
3153 3153
 			m.Target = &StoreAction_Secret{v}
3154 3154
 			iNdEx = postIndex
3155
+		case 8:
3156
+			if wireType != 2 {
3157
+				return fmt.Errorf("proto: wrong wireType = %d for field Resource", wireType)
3158
+			}
3159
+			var msglen int
3160
+			for shift := uint(0); ; shift += 7 {
3161
+				if shift >= 64 {
3162
+					return ErrIntOverflowRaft
3163
+				}
3164
+				if iNdEx >= l {
3165
+					return io.ErrUnexpectedEOF
3166
+				}
3167
+				b := dAtA[iNdEx]
3168
+				iNdEx++
3169
+				msglen |= (int(b) & 0x7F) << shift
3170
+				if b < 0x80 {
3171
+					break
3172
+				}
3173
+			}
3174
+			if msglen < 0 {
3175
+				return ErrInvalidLengthRaft
3176
+			}
3177
+			postIndex := iNdEx + msglen
3178
+			if postIndex > l {
3179
+				return io.ErrUnexpectedEOF
3180
+			}
3181
+			v := &Resource{}
3182
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3183
+				return err
3184
+			}
3185
+			m.Target = &StoreAction_Resource{v}
3186
+			iNdEx = postIndex
3187
+		case 9:
3188
+			if wireType != 2 {
3189
+				return fmt.Errorf("proto: wrong wireType = %d for field Extension", wireType)
3190
+			}
3191
+			var msglen int
3192
+			for shift := uint(0); ; shift += 7 {
3193
+				if shift >= 64 {
3194
+					return ErrIntOverflowRaft
3195
+				}
3196
+				if iNdEx >= l {
3197
+					return io.ErrUnexpectedEOF
3198
+				}
3199
+				b := dAtA[iNdEx]
3200
+				iNdEx++
3201
+				msglen |= (int(b) & 0x7F) << shift
3202
+				if b < 0x80 {
3203
+					break
3204
+				}
3205
+			}
3206
+			if msglen < 0 {
3207
+				return ErrInvalidLengthRaft
3208
+			}
3209
+			postIndex := iNdEx + msglen
3210
+			if postIndex > l {
3211
+				return io.ErrUnexpectedEOF
3212
+			}
3213
+			v := &Extension{}
3214
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3215
+				return err
3216
+			}
3217
+			m.Target = &StoreAction_Extension{v}
3218
+			iNdEx = postIndex
3155 3219
 		default:
3156 3220
 			iNdEx = preIndex
3157 3221
 			skippy, err := skipRaft(dAtA[iNdEx:])
... ...
@@ -3281,61 +3484,64 @@ var (
3281 3281
 func init() { proto.RegisterFile("raft.proto", fileDescriptorRaft) }
3282 3282
 
3283 3283
 var fileDescriptorRaft = []byte{
3284
-	// 885 bytes of a gzipped FileDescriptorProto
3285
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x95, 0xcf, 0x73, 0xdb, 0x44,
3286
-	0x14, 0xc7, 0x2d, 0x59, 0x95, 0xe1, 0xb9, 0x89, 0x33, 0x1b, 0x12, 0x54, 0xc1, 0x28, 0xaa, 0xca,
3287
-	0x4c, 0xdd, 0x0e, 0x91, 0x07, 0xc1, 0x4c, 0x19, 0xe0, 0x12, 0x27, 0x9e, 0x89, 0x69, 0xeb, 0x74,
3288
-	0x94, 0x04, 0x7a, 0x0b, 0xb2, 0xb4, 0x71, 0x85, 0x63, 0xad, 0xd9, 0x5d, 0x3b, 0xc3, 0x85, 0xe9,
3289
-	0x91, 0xc9, 0x95, 0xe1, 0xc7, 0xa5, 0x27, 0x38, 0xf7, 0x0f, 0xe0, 0x2f, 0xc8, 0x70, 0xe2, 0x06,
3290
-	0xa7, 0x0c, 0xf5, 0x1f, 0x00, 0xff, 0x02, 0xb3, 0x2b, 0x29, 0x49, 0x1d, 0xc5, 0xc9, 0x25, 0x59,
3291
-	0xaf, 0x3e, 0xdf, 0xf7, 0xdd, 0xf7, 0x56, 0xef, 0x09, 0x80, 0x06, 0xfb, 0xdc, 0x1d, 0x52, 0xc2,
3292
-	0x09, 0x42, 0x11, 0x09, 0xfb, 0x98, 0xba, 0xec, 0x30, 0xa0, 0x83, 0x7e, 0xcc, 0xdd, 0xf1, 0x07,
3293
-	0xe6, 0x1c, 0xe9, 0x7e, 0x8d, 0x43, 0xce, 0x52, 0xc4, 0xac, 0xf2, 0x6f, 0x87, 0x38, 0xff, 0xb1,
3294
-	0xda, 0x8b, 0xf9, 0xb3, 0x51, 0xd7, 0x0d, 0xc9, 0xa0, 0x11, 0x12, 0x8a, 0x09, 0x6b, 0x60, 0x1e,
3295
-	0x46, 0x0d, 0x11, 0x52, 0xfe, 0x19, 0x76, 0x1b, 0x67, 0xe1, 0xcd, 0xb7, 0x7a, 0xa4, 0x47, 0xe4,
3296
-	0xb2, 0x21, 0x56, 0xd9, 0xee, 0xe2, 0xf0, 0x60, 0xd4, 0x8b, 0x93, 0x46, 0xfa, 0x2f, 0xdd, 0x74,
3297
-	0x5e, 0x2a, 0x00, 0x7e, 0xb0, 0xcf, 0x1f, 0xe3, 0x41, 0x17, 0x53, 0x74, 0x07, 0x2a, 0x22, 0xce,
3298
-	0x5e, 0x1c, 0x19, 0x8a, 0xad, 0xd4, 0xb5, 0x26, 0x4c, 0x4e, 0x56, 0x74, 0x01, 0xb4, 0x37, 0x7c,
3299
-	0x5d, 0x3c, 0x6a, 0x47, 0x02, 0x4a, 0x48, 0x84, 0x05, 0xa4, 0xda, 0x4a, 0xfd, 0xcd, 0x14, 0xea,
3300
-	0x90, 0x08, 0x0b, 0x48, 0x3c, 0x6a, 0x47, 0x08, 0x81, 0x16, 0x44, 0x11, 0x35, 0xca, 0x82, 0xf0,
3301
-	0xe5, 0x1a, 0x35, 0x41, 0x67, 0x3c, 0xe0, 0x23, 0x66, 0x68, 0xb6, 0x52, 0xaf, 0x7a, 0xef, 0xb9,
3302
-	0x17, 0xeb, 0xe0, 0x9e, 0x9d, 0x66, 0x5b, 0xb2, 0x4d, 0xed, 0xf8, 0x64, 0xa5, 0xe4, 0x67, 0x4a,
3303
-	0xe7, 0x36, 0x54, 0x3f, 0x27, 0x71, 0xe2, 0xe3, 0x6f, 0x46, 0x98, 0xf1, 0x53, 0x1b, 0xe5, 0xcc,
3304
-	0xc6, 0xf9, 0x49, 0x81, 0x9b, 0x29, 0xc3, 0x86, 0x24, 0x61, 0xf8, 0x7a, 0x59, 0x7d, 0x0c, 0x95,
3305
-	0x81, 0xb4, 0x65, 0x86, 0x6a, 0x97, 0xeb, 0x55, 0xcf, 0x9a, 0x7d, 0x3a, 0x3f, 0xc7, 0xd1, 0x5d,
3306
-	0xa8, 0x51, 0x3c, 0x20, 0x63, 0x1c, 0xed, 0xe5, 0x11, 0xca, 0x76, 0xb9, 0xae, 0xf9, 0xf3, 0xd9,
3307
-	0x76, 0x2a, 0x60, 0x4e, 0x13, 0x6e, 0x3e, 0xc2, 0xc1, 0x18, 0xe7, 0x87, 0xf7, 0x40, 0x13, 0xd5,
3308
-	0x92, 0x87, 0xba, 0xda, 0x4f, 0xb2, 0x4e, 0x0d, 0xe6, 0xb2, 0x18, 0x69, 0x72, 0xce, 0x23, 0xb8,
3309
-	0xf5, 0x84, 0x92, 0x10, 0x33, 0x96, 0xb2, 0x8c, 0x05, 0xbd, 0x53, 0x87, 0x7b, 0x22, 0x29, 0xb9,
3310
-	0x93, 0x99, 0xd4, 0xdc, 0xf4, 0x75, 0x71, 0x73, 0x30, 0x7f, 0xfe, 0x89, 0xf6, 0xfc, 0x67, 0xa7,
3311
-	0xe4, 0xbc, 0x0b, 0x66, 0x51, 0xb4, 0xcc, 0xeb, 0x33, 0x58, 0xf2, 0x31, 0x23, 0x07, 0x63, 0xbc,
3312
-	0x16, 0x45, 0x54, 0x40, 0x99, 0xcf, 0x75, 0x2a, 0xec, 0xbc, 0x0f, 0xcb, 0xd3, 0xea, 0xec, 0x82,
3313
-	0x8a, 0x6e, 0x71, 0x1f, 0x16, 0xdb, 0x09, 0xc7, 0x34, 0x09, 0x0e, 0x44, 0x9c, 0xdc, 0x69, 0x19,
3314
-	0xd4, 0x53, 0x13, 0x7d, 0x72, 0xb2, 0xa2, 0xb6, 0x37, 0x7c, 0x35, 0x8e, 0xd0, 0x03, 0xd0, 0x83,
3315
-	0x90, 0xc7, 0x24, 0xc9, 0x6e, 0x6f, 0xa5, 0xa8, 0x9a, 0xdb, 0x9c, 0x50, 0xbc, 0x26, 0x31, 0x3f,
3316
-	0xc3, 0x9d, 0x1f, 0xcb, 0x50, 0x3d, 0xb7, 0x8f, 0x3e, 0x3d, 0x0d, 0x24, 0x4c, 0xe6, 0xbd, 0x3b,
3317
-	0x57, 0x04, 0x7a, 0x18, 0x27, 0x51, 0x1e, 0x0c, 0xb9, 0xd9, 0x8d, 0xaa, 0xb2, 0xd8, 0x46, 0x91,
3318
-	0x54, 0xf4, 0xc9, 0x66, 0x29, 0xbd, 0x4d, 0xf4, 0x00, 0x2a, 0x0c, 0xd3, 0x71, 0x1c, 0x62, 0xd9,
3319
-	0x28, 0x55, 0xef, 0x9d, 0x42, 0xb7, 0x14, 0xd9, 0x2c, 0xf9, 0x39, 0x2d, 0x8c, 0x78, 0xc0, 0xfa,
3320
-	0x59, 0x23, 0x15, 0x1a, 0xed, 0x04, 0xac, 0x2f, 0x8c, 0x04, 0x27, 0x8c, 0x12, 0xcc, 0x0f, 0x09,
3321
-	0xed, 0x1b, 0x37, 0x2e, 0x37, 0xea, 0xa4, 0x88, 0x30, 0xca, 0x68, 0x21, 0x0c, 0x0f, 0x46, 0x8c,
3322
-	0x63, 0x6a, 0xe8, 0x97, 0x0b, 0xd7, 0x53, 0x44, 0x08, 0x33, 0x1a, 0x7d, 0x04, 0x3a, 0xc3, 0x21,
3323
-	0xc5, 0xdc, 0xa8, 0x48, 0x9d, 0x59, 0x9c, 0x99, 0x20, 0x36, 0x45, 0x7b, 0xcb, 0x55, 0xf3, 0x0d,
3324
-	0xd0, 0x79, 0x40, 0x7b, 0x98, 0xdf, 0xff, 0x4f, 0x81, 0xda, 0x54, 0x99, 0xd1, 0x5d, 0xa8, 0xec,
3325
-	0x76, 0x1e, 0x76, 0xb6, 0xbe, 0xec, 0x2c, 0x94, 0x4c, 0xf3, 0xe8, 0x85, 0xbd, 0x3c, 0x45, 0xec,
3326
-	0x26, 0xfd, 0x84, 0x1c, 0x26, 0xc8, 0x83, 0xc5, 0xed, 0x9d, 0x2d, 0xbf, 0xb5, 0xb7, 0xb6, 0xbe,
3327
-	0xd3, 0xde, 0xea, 0xec, 0xad, 0xfb, 0xad, 0xb5, 0x9d, 0xd6, 0x82, 0x62, 0xde, 0x3a, 0x7a, 0x61,
3328
-	0x2f, 0x4d, 0x89, 0xd6, 0x29, 0x0e, 0x38, 0xbe, 0xa0, 0xd9, 0x7d, 0xb2, 0x21, 0x34, 0x6a, 0xa1,
3329
-	0x66, 0x77, 0x18, 0x15, 0x69, 0xfc, 0xd6, 0xe3, 0xad, 0x2f, 0x5a, 0x0b, 0xe5, 0x42, 0x8d, 0x2f,
3330
-	0xa7, 0x81, 0xf9, 0xf6, 0xf7, 0xbf, 0x5a, 0xa5, 0xdf, 0x7f, 0xb3, 0xa6, 0xb3, 0xf3, 0x7e, 0x50,
3331
-	0x41, 0x13, 0xaf, 0x3a, 0x3a, 0x52, 0x00, 0x5d, 0xec, 0x42, 0xb4, 0x5a, 0x54, 0xc1, 0x4b, 0x7b,
3332
-	0xdf, 0x74, 0xaf, 0x8b, 0x67, 0xcd, 0xbd, 0xf4, 0xc7, 0xcb, 0x7f, 0x7f, 0x51, 0x6b, 0x30, 0x27,
3333
-	0xf9, 0xd5, 0x41, 0x90, 0x04, 0x3d, 0x4c, 0xd1, 0x77, 0x30, 0xff, 0x7a, 0xd7, 0xa2, 0x7b, 0x85,
3334
-	0x83, 0xaa, 0x68, 0x2e, 0x98, 0xf7, 0xaf, 0x83, 0xce, 0xf4, 0xf7, 0xfe, 0x52, 0x60, 0xfe, 0x6c,
3335
-	0x0a, 0xb2, 0x67, 0xf1, 0x10, 0x7d, 0x05, 0x9a, 0x98, 0xef, 0xa8, 0xb0, 0xc7, 0xcf, 0x7d, 0x1d,
3336
-	0x4c, 0xfb, 0x72, 0x60, 0x76, 0xd2, 0x21, 0xdc, 0x90, 0x53, 0x16, 0x15, 0x46, 0x38, 0x3f, 0xc4,
3337
-	0xcd, 0xdb, 0x33, 0x88, 0x99, 0x26, 0x4d, 0xe3, 0xf8, 0x95, 0x55, 0xfa, 0xfb, 0x95, 0x55, 0x7a,
3338
-	0x3e, 0xb1, 0x94, 0xe3, 0x89, 0xa5, 0xfc, 0x39, 0xb1, 0x94, 0x7f, 0x26, 0x96, 0xf2, 0xb4, 0xfc,
3339
-	0x54, 0xeb, 0xea, 0xf2, 0x03, 0xfd, 0xe1, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x5a, 0xbd,
3340
-	0x08, 0x38, 0x08, 0x00, 0x00,
3284
+	// 933 bytes of a gzipped FileDescriptorProto
3285
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x96, 0x41, 0x73, 0xdb, 0x44,
3286
+	0x14, 0xc7, 0x25, 0x5b, 0xb5, 0x9b, 0xe7, 0x26, 0xce, 0x6c, 0x48, 0x50, 0x45, 0x51, 0x5c, 0x95,
3287
+	0x99, 0xba, 0x1d, 0x22, 0x0f, 0x86, 0x19, 0x98, 0x42, 0x0f, 0x71, 0xe2, 0x19, 0x9b, 0xb6, 0x4e,
3288
+	0x47, 0x49, 0xa0, 0xb7, 0x20, 0x4b, 0x5b, 0x57, 0xd8, 0xd6, 0x9a, 0xdd, 0xb5, 0x03, 0x17, 0xa6,
3289
+	0x47, 0x26, 0x27, 0x66, 0x98, 0x01, 0x2e, 0x3d, 0xc1, 0xb9, 0x1f, 0x80, 0x4f, 0x90, 0xe1, 0xc4,
3290
+	0x0d, 0x4e, 0x19, 0xea, 0x0f, 0x00, 0x5f, 0x81, 0xd9, 0x95, 0x64, 0x07, 0x47, 0x76, 0x73, 0xb1,
3291
+	0xd7, 0xbb, 0xbf, 0xff, 0xfb, 0xef, 0xee, 0xd3, 0x7b, 0x32, 0x00, 0x75, 0x9f, 0x72, 0x7b, 0x40,
3292
+	0x09, 0x27, 0x08, 0xf9, 0xc4, 0xeb, 0x62, 0x6a, 0xb3, 0x63, 0x97, 0xf6, 0xbb, 0x01, 0xb7, 0x47,
3293
+	0xef, 0x19, 0xcb, 0xa4, 0xfd, 0x25, 0xf6, 0x38, 0x8b, 0x10, 0xa3, 0xc0, 0xbf, 0x19, 0xe0, 0xe4,
3294
+	0xc7, 0x56, 0x27, 0xe0, 0xcf, 0x86, 0x6d, 0xdb, 0x23, 0xfd, 0x8a, 0x47, 0x28, 0x26, 0xac, 0x82,
3295
+	0xb9, 0xe7, 0x57, 0x44, 0x48, 0xf9, 0x31, 0x68, 0x57, 0xa6, 0xe1, 0x8d, 0x37, 0x3a, 0xa4, 0x43,
3296
+	0xe4, 0xb0, 0x22, 0x46, 0xf1, 0xec, 0xda, 0xa0, 0x37, 0xec, 0x04, 0x61, 0x25, 0xfa, 0x8a, 0x26,
3297
+	0xad, 0x97, 0x2a, 0x80, 0xe3, 0x3e, 0xe5, 0x8f, 0x70, 0xbf, 0x8d, 0x29, 0xba, 0x05, 0x79, 0x11,
3298
+	0xe7, 0x28, 0xf0, 0x75, 0xb5, 0xa4, 0x96, 0xb5, 0x1a, 0x8c, 0xcf, 0x36, 0x73, 0x02, 0x68, 0xee,
3299
+	0x3a, 0x39, 0xb1, 0xd4, 0xf4, 0x05, 0x14, 0x12, 0x1f, 0x0b, 0x28, 0x53, 0x52, 0xcb, 0x4b, 0x11,
3300
+	0xd4, 0x22, 0x3e, 0x16, 0x90, 0x58, 0x6a, 0xfa, 0x08, 0x81, 0xe6, 0xfa, 0x3e, 0xd5, 0xb3, 0x82,
3301
+	0x70, 0xe4, 0x18, 0xd5, 0x20, 0xc7, 0xb8, 0xcb, 0x87, 0x4c, 0xd7, 0x4a, 0x6a, 0xb9, 0x50, 0x7d,
3302
+	0xc7, 0xbe, 0x78, 0x0f, 0xf6, 0x74, 0x37, 0xfb, 0x92, 0xad, 0x69, 0xa7, 0x67, 0x9b, 0x8a, 0x13,
3303
+	0x2b, 0xad, 0x9b, 0x50, 0xf8, 0x94, 0x04, 0xa1, 0x83, 0xbf, 0x1a, 0x62, 0xc6, 0x27, 0x36, 0xea,
3304
+	0xd4, 0xc6, 0xfa, 0x51, 0x85, 0x6b, 0x11, 0xc3, 0x06, 0x24, 0x64, 0xf8, 0x72, 0xa7, 0xfa, 0x08,
3305
+	0xf2, 0x7d, 0x69, 0xcb, 0xf4, 0x4c, 0x29, 0x5b, 0x2e, 0x54, 0xcd, 0xc5, 0xbb, 0x73, 0x12, 0x1c,
3306
+	0xdd, 0x86, 0x22, 0xc5, 0x7d, 0x32, 0xc2, 0xfe, 0x51, 0x12, 0x21, 0x5b, 0xca, 0x96, 0x35, 0x67,
3307
+	0x25, 0x9e, 0x8e, 0x04, 0xcc, 0xaa, 0xc1, 0xb5, 0x87, 0xd8, 0x1d, 0xe1, 0x64, 0xf3, 0x55, 0xd0,
3308
+	0xc4, 0x6d, 0xc9, 0x4d, 0xbd, 0xde, 0x4f, 0xb2, 0x56, 0x11, 0x96, 0xe3, 0x18, 0xd1, 0xe1, 0xac,
3309
+	0x87, 0x70, 0xfd, 0x31, 0x25, 0x1e, 0x66, 0x2c, 0x62, 0x19, 0x73, 0x3b, 0x13, 0x87, 0x3b, 0xe2,
3310
+	0x50, 0x72, 0x26, 0x36, 0x29, 0xda, 0xd1, 0xe3, 0x62, 0x27, 0x60, 0xb2, 0x7e, 0x4f, 0x7b, 0xfe,
3311
+	0x93, 0xa5, 0x58, 0x37, 0xc0, 0x48, 0x8b, 0x16, 0x7b, 0x7d, 0x02, 0xeb, 0x0e, 0x66, 0xa4, 0x37,
3312
+	0xc2, 0xdb, 0xbe, 0x4f, 0x05, 0x14, 0xfb, 0x5c, 0xe6, 0x86, 0xad, 0x77, 0x61, 0x63, 0x56, 0x1d,
3313
+	0x27, 0x28, 0x2d, 0x8b, 0x3d, 0x58, 0x6b, 0x86, 0x1c, 0xd3, 0xd0, 0xed, 0x89, 0x38, 0x89, 0xd3,
3314
+	0x06, 0x64, 0x26, 0x26, 0xb9, 0xf1, 0xd9, 0x66, 0xa6, 0xb9, 0xeb, 0x64, 0x02, 0x1f, 0xdd, 0x87,
3315
+	0x9c, 0xeb, 0xf1, 0x80, 0x84, 0x71, 0xf6, 0x36, 0xd3, 0x6e, 0x73, 0x9f, 0x13, 0x8a, 0xb7, 0x25,
3316
+	0x96, 0x3c, 0x56, 0x91, 0xc8, 0xfa, 0x5e, 0x83, 0xc2, 0xb9, 0x55, 0xf4, 0xf1, 0x24, 0x9c, 0xb0,
3317
+	0x5a, 0xa9, 0xde, 0x7a, 0x4d, 0xb8, 0x07, 0x41, 0xe8, 0x27, 0xc1, 0x90, 0x1d, 0xe7, 0x35, 0x23,
3318
+	0xaf, 0x5c, 0x4f, 0x93, 0x8a, 0x6a, 0x69, 0x28, 0x51, 0x4e, 0xd1, 0x87, 0x90, 0x67, 0x98, 0x8e,
3319
+	0x02, 0x0f, 0xcb, 0x72, 0x29, 0x54, 0xdf, 0x4a, 0x75, 0x8b, 0x90, 0x86, 0xe2, 0x24, 0xb4, 0x30,
3320
+	0xe2, 0x2e, 0xeb, 0xc6, 0xe5, 0x94, 0x6a, 0x74, 0xe0, 0xb2, 0xae, 0x30, 0x12, 0x9c, 0x30, 0x0a,
3321
+	0x31, 0x3f, 0x26, 0xb4, 0xab, 0x5f, 0x99, 0x6f, 0xd4, 0x8a, 0x10, 0x61, 0x14, 0xd3, 0x42, 0xe8,
3322
+	0xf5, 0x86, 0x8c, 0x63, 0xaa, 0xe7, 0xe6, 0x0b, 0x77, 0x22, 0x44, 0x08, 0x63, 0x1a, 0x7d, 0x00,
3323
+	0x39, 0x86, 0x3d, 0x8a, 0xb9, 0x9e, 0x97, 0x3a, 0x23, 0xfd, 0x64, 0x82, 0x68, 0x88, 0x22, 0x97,
3324
+	0x23, 0x74, 0x0f, 0xae, 0x52, 0xcc, 0xc8, 0x90, 0x7a, 0x58, 0xbf, 0x2a, 0x75, 0x37, 0x52, 0x8b,
3325
+	0x23, 0x66, 0x1a, 0x8a, 0x33, 0xe1, 0xd1, 0x7d, 0x58, 0xc2, 0x5f, 0x73, 0x1c, 0x32, 0x91, 0xbc,
3326
+	0x25, 0x29, 0x7e, 0x3b, 0x4d, 0x5c, 0x4f, 0xa0, 0x86, 0xe2, 0x4c, 0x15, 0xb5, 0xab, 0x90, 0xe3,
3327
+	0x2e, 0xed, 0x60, 0x7e, 0xf7, 0x5f, 0x15, 0x8a, 0x33, 0x19, 0x46, 0xb7, 0x21, 0x7f, 0xd8, 0x7a,
3328
+	0xd0, 0xda, 0xfb, 0xbc, 0xb5, 0xaa, 0x18, 0xc6, 0xc9, 0x8b, 0xd2, 0xc6, 0x0c, 0x71, 0x18, 0x76,
3329
+	0x43, 0x72, 0x1c, 0xa2, 0x2a, 0xac, 0xed, 0x1f, 0xec, 0x39, 0xf5, 0xa3, 0xed, 0x9d, 0x83, 0xe6,
3330
+	0x5e, 0xeb, 0x68, 0xc7, 0xa9, 0x6f, 0x1f, 0xd4, 0x57, 0x55, 0xe3, 0xfa, 0xc9, 0x8b, 0xd2, 0xfa,
3331
+	0x8c, 0x68, 0x87, 0x62, 0x97, 0xe3, 0x0b, 0x9a, 0xc3, 0xc7, 0xbb, 0x42, 0x93, 0x49, 0xd5, 0x1c,
3332
+	0x0e, 0xfc, 0x34, 0x8d, 0x53, 0x7f, 0xb4, 0xf7, 0x59, 0x7d, 0x35, 0x9b, 0xaa, 0x71, 0x64, 0x3b,
3333
+	0x32, 0xde, 0xfc, 0xee, 0x17, 0x53, 0xf9, 0xed, 0x57, 0x73, 0xf6, 0x74, 0xd5, 0x1f, 0x32, 0xa0,
3334
+	0x89, 0x5a, 0x43, 0x27, 0x2a, 0xa0, 0x8b, 0x6d, 0x00, 0x6d, 0xa5, 0xdd, 0xe3, 0xdc, 0xe6, 0x63,
3335
+	0xd8, 0x97, 0xc5, 0xe3, 0xee, 0xb2, 0xfe, 0xfb, 0xcb, 0x7f, 0x7e, 0xce, 0x14, 0x61, 0x59, 0xf2,
3336
+	0x5b, 0x7d, 0x37, 0x74, 0x3b, 0x98, 0xa2, 0x6f, 0x61, 0xe5, 0xff, 0x6d, 0x03, 0xdd, 0x99, 0xf7,
3337
+	0x30, 0x5c, 0x68, 0x4c, 0xc6, 0xdd, 0xcb, 0xa0, 0x0b, 0xfd, 0xab, 0x7f, 0xaa, 0xb0, 0x32, 0x6d,
3338
+	0xc3, 0xec, 0x59, 0x30, 0x40, 0x5f, 0x80, 0x26, 0x5e, 0x30, 0x28, 0xb5, 0xc9, 0x9c, 0x7b, 0x3d,
3339
+	0x19, 0xa5, 0xf9, 0xc0, 0xe2, 0x43, 0x7b, 0x70, 0x45, 0xb6, 0x79, 0x94, 0x1a, 0xe1, 0xfc, 0x5b,
3340
+	0xc4, 0xb8, 0xb9, 0x80, 0x58, 0x68, 0x52, 0xd3, 0x4f, 0x5f, 0x99, 0xca, 0x5f, 0xaf, 0x4c, 0xe5,
3341
+	0xf9, 0xd8, 0x54, 0x4f, 0xc7, 0xa6, 0xfa, 0xc7, 0xd8, 0x54, 0xff, 0x1e, 0x9b, 0xea, 0x93, 0xec,
3342
+	0x13, 0xad, 0x9d, 0x93, 0xff, 0x10, 0xde, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x98, 0x55, 0x8d,
3343
+	0x81, 0xb9, 0x08, 0x00, 0x00,
3341 3344
 }
... ...
@@ -98,7 +98,7 @@ message ResolveAddressResponse {
98 98
 message InternalRaftRequest {
99 99
 	uint64 id = 1;
100 100
 
101
-	repeated StoreAction action = 2;
101
+	repeated StoreAction action = 2 [(gogoproto.nullable) = false];
102 102
 }
103 103
 
104 104
 // TODO(stevvooe): Storage actions may belong in another protobuf file. They
... ...
@@ -125,5 +125,7 @@ message StoreAction {
125 125
 		Network network = 5;
126 126
 		Cluster cluster = 6;
127 127
 		Secret secret = 7;
128
+		Resource resource = 8;
129
+		Extension extension = 9;
128 130
 	}
129 131
 }
... ...
@@ -43,12 +43,14 @@ func (Snapshot_Version) EnumDescriptor() ([]byte, []int) { return fileDescriptor
43 43
 
44 44
 // StoreSnapshot is used to store snapshots of the store.
45 45
 type StoreSnapshot struct {
46
-	Nodes    []*Node    `protobuf:"bytes,1,rep,name=nodes" json:"nodes,omitempty"`
47
-	Services []*Service `protobuf:"bytes,2,rep,name=services" json:"services,omitempty"`
48
-	Networks []*Network `protobuf:"bytes,3,rep,name=networks" json:"networks,omitempty"`
49
-	Tasks    []*Task    `protobuf:"bytes,4,rep,name=tasks" json:"tasks,omitempty"`
50
-	Clusters []*Cluster `protobuf:"bytes,5,rep,name=clusters" json:"clusters,omitempty"`
51
-	Secrets  []*Secret  `protobuf:"bytes,6,rep,name=secrets" json:"secrets,omitempty"`
46
+	Nodes      []*Node      `protobuf:"bytes,1,rep,name=nodes" json:"nodes,omitempty"`
47
+	Services   []*Service   `protobuf:"bytes,2,rep,name=services" json:"services,omitempty"`
48
+	Networks   []*Network   `protobuf:"bytes,3,rep,name=networks" json:"networks,omitempty"`
49
+	Tasks      []*Task      `protobuf:"bytes,4,rep,name=tasks" json:"tasks,omitempty"`
50
+	Clusters   []*Cluster   `protobuf:"bytes,5,rep,name=clusters" json:"clusters,omitempty"`
51
+	Secrets    []*Secret    `protobuf:"bytes,6,rep,name=secrets" json:"secrets,omitempty"`
52
+	Resources  []*Resource  `protobuf:"bytes,7,rep,name=resources" json:"resources,omitempty"`
53
+	Extensions []*Extension `protobuf:"bytes,8,rep,name=extensions" json:"extensions,omitempty"`
52 54
 }
53 55
 
54 56
 func (m *StoreSnapshot) Reset()                    { *m = StoreSnapshot{} }
... ...
@@ -143,6 +145,22 @@ func (m *StoreSnapshot) CopyFrom(src interface{}) {
143 143
 		}
144 144
 	}
145 145
 
146
+	if o.Resources != nil {
147
+		m.Resources = make([]*Resource, len(o.Resources))
148
+		for i := range m.Resources {
149
+			m.Resources[i] = &Resource{}
150
+			github_com_docker_swarmkit_api_deepcopy.Copy(m.Resources[i], o.Resources[i])
151
+		}
152
+	}
153
+
154
+	if o.Extensions != nil {
155
+		m.Extensions = make([]*Extension, len(o.Extensions))
156
+		for i := range m.Extensions {
157
+			m.Extensions[i] = &Extension{}
158
+			github_com_docker_swarmkit_api_deepcopy.Copy(m.Extensions[i], o.Extensions[i])
159
+		}
160
+	}
161
+
146 162
 }
147 163
 
148 164
 func (m *ClusterSnapshot) Copy() *ClusterSnapshot {
... ...
@@ -277,6 +295,30 @@ func (m *StoreSnapshot) MarshalTo(dAtA []byte) (int, error) {
277 277
 			i += n
278 278
 		}
279 279
 	}
280
+	if len(m.Resources) > 0 {
281
+		for _, msg := range m.Resources {
282
+			dAtA[i] = 0x3a
283
+			i++
284
+			i = encodeVarintSnapshot(dAtA, i, uint64(msg.Size()))
285
+			n, err := msg.MarshalTo(dAtA[i:])
286
+			if err != nil {
287
+				return 0, err
288
+			}
289
+			i += n
290
+		}
291
+	}
292
+	if len(m.Extensions) > 0 {
293
+		for _, msg := range m.Extensions {
294
+			dAtA[i] = 0x42
295
+			i++
296
+			i = encodeVarintSnapshot(dAtA, i, uint64(msg.Size()))
297
+			n, err := msg.MarshalTo(dAtA[i:])
298
+			if err != nil {
299
+				return 0, err
300
+			}
301
+			i += n
302
+		}
303
+	}
280 304
 	return i, nil
281 305
 }
282 306
 
... ...
@@ -433,6 +475,18 @@ func (m *StoreSnapshot) Size() (n int) {
433 433
 			n += 1 + l + sovSnapshot(uint64(l))
434 434
 		}
435 435
 	}
436
+	if len(m.Resources) > 0 {
437
+		for _, e := range m.Resources {
438
+			l = e.Size()
439
+			n += 1 + l + sovSnapshot(uint64(l))
440
+		}
441
+	}
442
+	if len(m.Extensions) > 0 {
443
+		for _, e := range m.Extensions {
444
+			l = e.Size()
445
+			n += 1 + l + sovSnapshot(uint64(l))
446
+		}
447
+	}
436 448
 	return n
437 449
 }
438 450
 
... ...
@@ -492,6 +546,8 @@ func (this *StoreSnapshot) String() string {
492 492
 		`Tasks:` + strings.Replace(fmt.Sprintf("%v", this.Tasks), "Task", "Task", 1) + `,`,
493 493
 		`Clusters:` + strings.Replace(fmt.Sprintf("%v", this.Clusters), "Cluster", "Cluster", 1) + `,`,
494 494
 		`Secrets:` + strings.Replace(fmt.Sprintf("%v", this.Secrets), "Secret", "Secret", 1) + `,`,
495
+		`Resources:` + strings.Replace(fmt.Sprintf("%v", this.Resources), "Resource", "Resource", 1) + `,`,
496
+		`Extensions:` + strings.Replace(fmt.Sprintf("%v", this.Extensions), "Extension", "Extension", 1) + `,`,
495 497
 		`}`,
496 498
 	}, "")
497 499
 	return s
... ...
@@ -742,6 +798,68 @@ func (m *StoreSnapshot) Unmarshal(dAtA []byte) error {
742 742
 				return err
743 743
 			}
744 744
 			iNdEx = postIndex
745
+		case 7:
746
+			if wireType != 2 {
747
+				return fmt.Errorf("proto: wrong wireType = %d for field Resources", wireType)
748
+			}
749
+			var msglen int
750
+			for shift := uint(0); ; shift += 7 {
751
+				if shift >= 64 {
752
+					return ErrIntOverflowSnapshot
753
+				}
754
+				if iNdEx >= l {
755
+					return io.ErrUnexpectedEOF
756
+				}
757
+				b := dAtA[iNdEx]
758
+				iNdEx++
759
+				msglen |= (int(b) & 0x7F) << shift
760
+				if b < 0x80 {
761
+					break
762
+				}
763
+			}
764
+			if msglen < 0 {
765
+				return ErrInvalidLengthSnapshot
766
+			}
767
+			postIndex := iNdEx + msglen
768
+			if postIndex > l {
769
+				return io.ErrUnexpectedEOF
770
+			}
771
+			m.Resources = append(m.Resources, &Resource{})
772
+			if err := m.Resources[len(m.Resources)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
773
+				return err
774
+			}
775
+			iNdEx = postIndex
776
+		case 8:
777
+			if wireType != 2 {
778
+				return fmt.Errorf("proto: wrong wireType = %d for field Extensions", wireType)
779
+			}
780
+			var msglen int
781
+			for shift := uint(0); ; shift += 7 {
782
+				if shift >= 64 {
783
+					return ErrIntOverflowSnapshot
784
+				}
785
+				if iNdEx >= l {
786
+					return io.ErrUnexpectedEOF
787
+				}
788
+				b := dAtA[iNdEx]
789
+				iNdEx++
790
+				msglen |= (int(b) & 0x7F) << shift
791
+				if b < 0x80 {
792
+					break
793
+				}
794
+			}
795
+			if msglen < 0 {
796
+				return ErrInvalidLengthSnapshot
797
+			}
798
+			postIndex := iNdEx + msglen
799
+			if postIndex > l {
800
+				return io.ErrUnexpectedEOF
801
+			}
802
+			m.Extensions = append(m.Extensions, &Extension{})
803
+			if err := m.Extensions[len(m.Extensions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
804
+				return err
805
+			}
806
+			iNdEx = postIndex
745 807
 		default:
746 808
 			iNdEx = preIndex
747 809
 			skippy, err := skipSnapshot(dAtA[iNdEx:])
... ...
@@ -1143,31 +1261,34 @@ var (
1143 1143
 func init() { proto.RegisterFile("snapshot.proto", fileDescriptorSnapshot) }
1144 1144
 
1145 1145
 var fileDescriptorSnapshot = []byte{
1146
-	// 404 bytes of a gzipped FileDescriptorProto
1147
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x92, 0xbd, 0x6e, 0xd4, 0x40,
1148
-	0x10, 0xc7, 0xbd, 0xbe, 0x0f, 0x47, 0x13, 0x25, 0xc0, 0x8a, 0x62, 0x65, 0x24, 0x73, 0x18, 0x8a,
1149
-	0xab, 0x0c, 0x1c, 0x48, 0xd0, 0x40, 0x11, 0x2a, 0x0a, 0x52, 0xec, 0xa1, 0x88, 0xd6, 0x67, 0x4f,
1150
-	0x12, 0x63, 0xec, 0x3d, 0xed, 0x2c, 0x4e, 0xcb, 0xe3, 0x5d, 0x99, 0x92, 0x0a, 0x11, 0x37, 0xbc,
1151
-	0x06, 0xb2, 0xd7, 0xb6, 0x4e, 0xc2, 0x47, 0x37, 0xb6, 0x7e, 0xff, 0x8f, 0x1d, 0x0d, 0x9c, 0x52,
1152
-	0x19, 0x6f, 0xe9, 0x5a, 0x99, 0x68, 0xab, 0x95, 0x51, 0x9c, 0xa7, 0x2a, 0xc9, 0x51, 0x47, 0x74,
1153
-	0x13, 0xeb, 0x22, 0xcf, 0x4c, 0x54, 0xbd, 0xf4, 0x4f, 0xd4, 0xe6, 0x2b, 0x26, 0x86, 0x2c, 0xe2,
1154
-	0x83, 0x8e, 0x2f, 0x3b, 0xdc, 0x7f, 0x78, 0xa5, 0xae, 0x54, 0x3b, 0x3e, 0x6f, 0x26, 0xfb, 0x37,
1155
-	0xbc, 0x75, 0xe1, 0x64, 0x6d, 0x94, 0xc6, 0x75, 0x67, 0xce, 0x23, 0x98, 0x95, 0x2a, 0x45, 0x12,
1156
-	0x6c, 0x31, 0x59, 0x1e, 0xaf, 0x44, 0xf4, 0x6f, 0x4c, 0x74, 0xae, 0x52, 0x94, 0x16, 0xe3, 0x6f,
1157
-	0xe0, 0x88, 0x50, 0x57, 0x59, 0x82, 0x24, 0xdc, 0x56, 0xf2, 0x68, 0x4c, 0xb2, 0xb6, 0x8c, 0x1c,
1158
-	0xe0, 0x46, 0x58, 0xa2, 0xb9, 0x51, 0x3a, 0x27, 0x31, 0x39, 0x2c, 0x3c, 0xb7, 0x8c, 0x1c, 0xe0,
1159
-	0xa6, 0xa1, 0x89, 0x29, 0x27, 0x31, 0x3d, 0xdc, 0xf0, 0x73, 0x4c, 0xb9, 0xb4, 0x58, 0x13, 0x94,
1160
-	0x7c, 0xfb, 0x4e, 0x06, 0x35, 0x89, 0xd9, 0xe1, 0xa0, 0x0f, 0x96, 0x91, 0x03, 0xcc, 0x5f, 0x83,
1161
-	0x47, 0x98, 0x68, 0x34, 0x24, 0xe6, 0xad, 0xce, 0x1f, 0x7f, 0x59, 0x83, 0xc8, 0x1e, 0x0d, 0x11,
1162
-	0xee, 0x75, 0x56, 0xc3, 0x4e, 0xdf, 0x82, 0x57, 0x60, 0xb1, 0x69, 0x0a, 0xd8, 0xad, 0x06, 0x63,
1163
-	0x46, 0x32, 0xbe, 0x34, 0x9f, 0x5a, 0x4c, 0xf6, 0x38, 0x17, 0xe0, 0x69, 0x2c, 0x54, 0x85, 0x69,
1164
-	0xbb, 0xdc, 0xa9, 0xec, 0x3f, 0xc3, 0x3f, 0x0c, 0x8e, 0x86, 0x80, 0xf7, 0xe0, 0x55, 0xa8, 0x29,
1165
-	0x53, 0xa5, 0x60, 0x0b, 0xb6, 0x3c, 0x5d, 0x3d, 0x1b, 0x6d, 0xda, 0x1f, 0xd0, 0x85, 0x65, 0x65,
1166
-	0x2f, 0xe2, 0x1f, 0x01, 0xba, 0xc4, 0xeb, 0x6c, 0x2b, 0xdc, 0x05, 0x5b, 0x1e, 0xaf, 0x9e, 0xfe,
1167
-	0x67, 0x49, 0xbd, 0xd3, 0xd9, 0x74, 0xf7, 0xeb, 0xb1, 0x23, 0xf7, 0xc4, 0xfc, 0x1d, 0xcc, 0xa8,
1168
-	0x39, 0x28, 0x31, 0x69, 0x5d, 0x9e, 0x8c, 0x16, 0xd9, 0xbf, 0xb8, 0xce, 0xc3, 0xaa, 0xc2, 0x07,
1169
-	0xe0, 0x75, 0xed, 0xf8, 0x1c, 0xdc, 0x8b, 0x17, 0xf7, 0x9d, 0x33, 0xb1, 0xbb, 0x0b, 0x9c, 0x9f,
1170
-	0x77, 0x81, 0xf3, 0xa3, 0x0e, 0xd8, 0xae, 0x0e, 0xd8, 0x6d, 0x1d, 0xb0, 0xdf, 0x75, 0xc0, 0xbe,
1171
-	0xb8, 0x9b, 0x79, 0x7b, 0xc6, 0xaf, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0xa4, 0x5b, 0x6d, 0xab,
1172
-	0x1d, 0x03, 0x00, 0x00,
1146
+	// 449 bytes of a gzipped FileDescriptorProto
1147
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x93, 0xbf, 0x6f, 0xd3, 0x40,
1148
+	0x14, 0xc7, 0x73, 0xf9, 0xe5, 0xf0, 0xaa, 0x16, 0x38, 0x31, 0x9c, 0x02, 0x98, 0x10, 0x18, 0x32,
1149
+	0x19, 0x08, 0x48, 0x20, 0xa4, 0x32, 0x14, 0x31, 0x30, 0xd0, 0xe1, 0x82, 0x2a, 0x56, 0xc7, 0x79,
1150
+	0x6d, 0x83, 0x89, 0x2f, 0xba, 0x77, 0x75, 0x19, 0xf9, 0xf3, 0x22, 0xb1, 0x30, 0x32, 0x21, 0xea,
1151
+	0x85, 0x7f, 0x03, 0xdd, 0x9d, 0x6d, 0x22, 0xe1, 0x74, 0xbb, 0x44, 0x9f, 0xcf, 0xfb, 0xbe, 0xbb,
1152
+	0xf7, 0x0c, 0x07, 0x94, 0xc5, 0x6b, 0x3a, 0x57, 0x26, 0x5a, 0x6b, 0x65, 0x14, 0xe7, 0x0b, 0x95,
1153
+	0xa4, 0xa8, 0x23, 0xba, 0x8c, 0xf5, 0x2a, 0x5d, 0x9a, 0x28, 0x7f, 0x36, 0xdc, 0x57, 0xf3, 0xcf,
1154
+	0x98, 0x18, 0xf2, 0xc8, 0x10, 0x74, 0x7c, 0x5a, 0xe2, 0xc3, 0x3b, 0x67, 0xea, 0x4c, 0xb9, 0xe3,
1155
+	0x13, 0x7b, 0xf2, 0xff, 0x8e, 0xbf, 0x77, 0x60, 0x7f, 0x66, 0x94, 0xc6, 0x59, 0x59, 0x9c, 0x47,
1156
+	0xd0, 0xcb, 0xd4, 0x02, 0x49, 0xb0, 0x51, 0x67, 0xb2, 0x37, 0x15, 0xd1, 0xff, 0x31, 0xd1, 0xb1,
1157
+	0x5a, 0xa0, 0xf4, 0x18, 0x7f, 0x09, 0x03, 0x42, 0x9d, 0x2f, 0x13, 0x24, 0xd1, 0x76, 0xca, 0xdd,
1158
+	0x26, 0x65, 0xe6, 0x19, 0x59, 0xc3, 0x56, 0xcc, 0xd0, 0x5c, 0x2a, 0x9d, 0x92, 0xe8, 0xec, 0x16,
1159
+	0x8f, 0x3d, 0x23, 0x6b, 0xd8, 0x76, 0x68, 0x62, 0x4a, 0x49, 0x74, 0x77, 0x77, 0xf8, 0x31, 0xa6,
1160
+	0x54, 0x7a, 0xcc, 0x06, 0x25, 0x5f, 0x2e, 0xc8, 0xa0, 0x26, 0xd1, 0xdb, 0x1d, 0xf4, 0xd6, 0x33,
1161
+	0xb2, 0x86, 0xf9, 0x0b, 0x08, 0x08, 0x13, 0x8d, 0x86, 0x44, 0xdf, 0x79, 0xc3, 0xe6, 0x9b, 0x59,
1162
+	0x44, 0x56, 0x28, 0x7f, 0x0d, 0x37, 0x34, 0x92, 0xba, 0xd0, 0xf6, 0x45, 0x02, 0xe7, 0xdd, 0x6b,
1163
+	0xf2, 0x64, 0x09, 0xc9, 0x7f, 0x38, 0x3f, 0x04, 0xc0, 0xaf, 0x06, 0x33, 0x5a, 0xaa, 0x8c, 0xc4,
1164
+	0xc0, 0xc9, 0xf7, 0x9b, 0xe4, 0x77, 0x15, 0x25, 0xb7, 0x84, 0x31, 0xc2, 0xcd, 0xf2, 0x16, 0xf5,
1165
+	0x38, 0x5f, 0x41, 0xb0, 0xc2, 0xd5, 0xdc, 0xde, 0xdd, 0x0f, 0x34, 0x6c, 0xec, 0x25, 0x3e, 0x35,
1166
+	0x1f, 0x1c, 0x26, 0x2b, 0x9c, 0x0b, 0x08, 0x34, 0xae, 0x54, 0x8e, 0x0b, 0x37, 0xd7, 0xae, 0xac,
1167
+	0x7e, 0x8e, 0xff, 0x30, 0x18, 0xd4, 0x01, 0x6f, 0x20, 0xc8, 0x51, 0xdb, 0x7c, 0xc1, 0x46, 0x6c,
1168
+	0x72, 0x30, 0x7d, 0xdc, 0xf8, 0x48, 0xd5, 0xee, 0x9e, 0x78, 0x56, 0x56, 0x12, 0x7f, 0x0f, 0x50,
1169
+	0x26, 0x9e, 0x2f, 0xd7, 0xa2, 0x3d, 0x62, 0x93, 0xbd, 0xe9, 0xa3, 0x6b, 0xe6, 0x53, 0x55, 0x3a,
1170
+	0xea, 0x6e, 0x7e, 0x3d, 0x68, 0xc9, 0x2d, 0x99, 0x1f, 0x42, 0x8f, 0xec, 0x2e, 0x8b, 0x8e, 0xab,
1171
+	0xf2, 0xb0, 0xb1, 0x91, 0xed, 0x65, 0x2f, 0x6b, 0x78, 0x6b, 0x7c, 0x1b, 0x82, 0xb2, 0x3b, 0xde,
1172
+	0x87, 0xf6, 0xc9, 0xd3, 0x5b, 0xad, 0x23, 0xb1, 0xb9, 0x0a, 0x5b, 0x3f, 0xaf, 0xc2, 0xd6, 0xb7,
1173
+	0x22, 0x64, 0x9b, 0x22, 0x64, 0x3f, 0x8a, 0x90, 0xfd, 0x2e, 0x42, 0xf6, 0xa9, 0x3d, 0xef, 0xbb,
1174
+	0x2f, 0xe8, 0xf9, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x91, 0xfe, 0xed, 0x18, 0x98, 0x03, 0x00,
1175
+	0x00,
1173 1176
 }
... ...
@@ -20,6 +20,8 @@ message StoreSnapshot {
20 20
 	repeated Task tasks = 4;
21 21
 	repeated Cluster clusters = 5;
22 22
 	repeated Secret secrets = 6;
23
+	repeated Resource resources = 7;
24
+	repeated Extension extensions = 8;
23 25
 }
24 26
 
25 27
 // ClusterSnapshot stores cluster membership information in snapshots.
... ...
@@ -9,6 +9,7 @@ import fmt "fmt"
9 9
 import math "math"
10 10
 import _ "github.com/gogo/protobuf/gogoproto"
11 11
 import google_protobuf1 "github.com/gogo/protobuf/types"
12
+import google_protobuf3 "github.com/gogo/protobuf/types"
12 13
 
13 14
 import github_com_docker_swarmkit_api_deepcopy "github.com/docker/swarmkit/api/deepcopy"
14 15
 
... ...
@@ -106,7 +107,7 @@ func (x EndpointSpec_ResolutionMode) String() string {
106 106
 	return proto.EnumName(EndpointSpec_ResolutionMode_name, int32(x))
107 107
 }
108 108
 func (EndpointSpec_ResolutionMode) EnumDescriptor() ([]byte, []int) {
109
-	return fileDescriptorSpecs, []int{7, 0}
109
+	return fileDescriptorSpecs, []int{8, 0}
110 110
 }
111 111
 
112 112
 type NodeSpec struct {
... ...
@@ -289,6 +290,7 @@ type TaskSpec struct {
289 289
 	// Types that are valid to be assigned to Runtime:
290 290
 	//	*TaskSpec_Attachment
291 291
 	//	*TaskSpec_Container
292
+	//	*TaskSpec_Generic
292 293
 	Runtime isTaskSpec_Runtime `protobuf_oneof:"runtime"`
293 294
 	// Resource requirements for the container.
294 295
 	Resources *ResourceRequirements `protobuf:"bytes,2,opt,name=resources" json:"resources,omitempty"`
... ...
@@ -326,9 +328,13 @@ type TaskSpec_Attachment struct {
326 326
 type TaskSpec_Container struct {
327 327
 	Container *ContainerSpec `protobuf:"bytes,1,opt,name=container,oneof"`
328 328
 }
329
+type TaskSpec_Generic struct {
330
+	Generic *GenericRuntimeSpec `protobuf:"bytes,10,opt,name=generic,oneof"`
331
+}
329 332
 
330 333
 func (*TaskSpec_Attachment) isTaskSpec_Runtime() {}
331 334
 func (*TaskSpec_Container) isTaskSpec_Runtime()  {}
335
+func (*TaskSpec_Generic) isTaskSpec_Runtime()    {}
332 336
 
333 337
 func (m *TaskSpec) GetRuntime() isTaskSpec_Runtime {
334 338
 	if m != nil {
... ...
@@ -351,11 +357,19 @@ func (m *TaskSpec) GetContainer() *ContainerSpec {
351 351
 	return nil
352 352
 }
353 353
 
354
+func (m *TaskSpec) GetGeneric() *GenericRuntimeSpec {
355
+	if x, ok := m.GetRuntime().(*TaskSpec_Generic); ok {
356
+		return x.Generic
357
+	}
358
+	return nil
359
+}
360
+
354 361
 // XXX_OneofFuncs is for the internal use of the proto package.
355 362
 func (*TaskSpec) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
356 363
 	return _TaskSpec_OneofMarshaler, _TaskSpec_OneofUnmarshaler, _TaskSpec_OneofSizer, []interface{}{
357 364
 		(*TaskSpec_Attachment)(nil),
358 365
 		(*TaskSpec_Container)(nil),
366
+		(*TaskSpec_Generic)(nil),
359 367
 	}
360 368
 }
361 369
 
... ...
@@ -373,6 +387,11 @@ func _TaskSpec_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
373 373
 		if err := b.EncodeMessage(x.Container); err != nil {
374 374
 			return err
375 375
 		}
376
+	case *TaskSpec_Generic:
377
+		_ = b.EncodeVarint(10<<3 | proto.WireBytes)
378
+		if err := b.EncodeMessage(x.Generic); err != nil {
379
+			return err
380
+		}
376 381
 	case nil:
377 382
 	default:
378 383
 		return fmt.Errorf("TaskSpec.Runtime has unexpected type %T", x)
... ...
@@ -399,6 +418,14 @@ func _TaskSpec_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe
399 399
 		err := b.DecodeMessage(msg)
400 400
 		m.Runtime = &TaskSpec_Container{msg}
401 401
 		return true, err
402
+	case 10: // runtime.generic
403
+		if wire != proto.WireBytes {
404
+			return true, proto.ErrInternalBadWireType
405
+		}
406
+		msg := new(GenericRuntimeSpec)
407
+		err := b.DecodeMessage(msg)
408
+		m.Runtime = &TaskSpec_Generic{msg}
409
+		return true, err
402 410
 	default:
403 411
 		return false, nil
404 412
 	}
... ...
@@ -418,6 +445,11 @@ func _TaskSpec_OneofSizer(msg proto.Message) (n int) {
418 418
 		n += proto.SizeVarint(1<<3 | proto.WireBytes)
419 419
 		n += proto.SizeVarint(uint64(s))
420 420
 		n += s
421
+	case *TaskSpec_Generic:
422
+		s := proto.Size(x.Generic)
423
+		n += proto.SizeVarint(10<<3 | proto.WireBytes)
424
+		n += proto.SizeVarint(uint64(s))
425
+		n += s
421 426
 	case nil:
422 427
 	default:
423 428
 		panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
... ...
@@ -425,6 +457,15 @@ func _TaskSpec_OneofSizer(msg proto.Message) (n int) {
425 425
 	return n
426 426
 }
427 427
 
428
+type GenericRuntimeSpec struct {
429
+	Kind    string                `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"`
430
+	Payload *google_protobuf3.Any `protobuf:"bytes,2,opt,name=payload" json:"payload,omitempty"`
431
+}
432
+
433
+func (m *GenericRuntimeSpec) Reset()                    { *m = GenericRuntimeSpec{} }
434
+func (*GenericRuntimeSpec) ProtoMessage()               {}
435
+func (*GenericRuntimeSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{5} }
436
+
428 437
 // NetworkAttachmentSpec specifies runtime parameters required to attach
429 438
 // a container to a network.
430 439
 type NetworkAttachmentSpec struct {
... ...
@@ -435,7 +476,7 @@ type NetworkAttachmentSpec struct {
435 435
 
436 436
 func (m *NetworkAttachmentSpec) Reset()                    { *m = NetworkAttachmentSpec{} }
437 437
 func (*NetworkAttachmentSpec) ProtoMessage()               {}
438
-func (*NetworkAttachmentSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{5} }
438
+func (*NetworkAttachmentSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{6} }
439 439
 
440 440
 // Container specifies runtime parameters for a container.
441 441
 type ContainerSpec struct {
... ...
@@ -525,7 +566,7 @@ type ContainerSpec struct {
525 525
 
526 526
 func (m *ContainerSpec) Reset()                    { *m = ContainerSpec{} }
527 527
 func (*ContainerSpec) ProtoMessage()               {}
528
-func (*ContainerSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{6} }
528
+func (*ContainerSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{7} }
529 529
 
530 530
 // PullOptions allows one to parameterize an image pull.
531 531
 type ContainerSpec_PullOptions struct {
... ...
@@ -539,7 +580,7 @@ type ContainerSpec_PullOptions struct {
539 539
 func (m *ContainerSpec_PullOptions) Reset()      { *m = ContainerSpec_PullOptions{} }
540 540
 func (*ContainerSpec_PullOptions) ProtoMessage() {}
541 541
 func (*ContainerSpec_PullOptions) Descriptor() ([]byte, []int) {
542
-	return fileDescriptorSpecs, []int{6, 1}
542
+	return fileDescriptorSpecs, []int{7, 1}
543 543
 }
544 544
 
545 545
 // DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
... ...
@@ -557,7 +598,7 @@ type ContainerSpec_DNSConfig struct {
557 557
 
558 558
 func (m *ContainerSpec_DNSConfig) Reset()                    { *m = ContainerSpec_DNSConfig{} }
559 559
 func (*ContainerSpec_DNSConfig) ProtoMessage()               {}
560
-func (*ContainerSpec_DNSConfig) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{6, 2} }
560
+func (*ContainerSpec_DNSConfig) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{7, 2} }
561 561
 
562 562
 // EndpointSpec defines the properties that can be configured to
563 563
 // access and loadbalance the service.
... ...
@@ -570,7 +611,7 @@ type EndpointSpec struct {
570 570
 
571 571
 func (m *EndpointSpec) Reset()                    { *m = EndpointSpec{} }
572 572
 func (*EndpointSpec) ProtoMessage()               {}
573
-func (*EndpointSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{7} }
573
+func (*EndpointSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{8} }
574 574
 
575 575
 // NetworkSpec specifies user defined network parameters.
576 576
 type NetworkSpec struct {
... ...
@@ -600,7 +641,7 @@ type NetworkSpec struct {
600 600
 
601 601
 func (m *NetworkSpec) Reset()                    { *m = NetworkSpec{} }
602 602
 func (*NetworkSpec) ProtoMessage()               {}
603
-func (*NetworkSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{8} }
603
+func (*NetworkSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{9} }
604 604
 
605 605
 // ClusterSpec specifies global cluster settings.
606 606
 type ClusterSpec struct {
... ...
@@ -625,7 +666,7 @@ type ClusterSpec struct {
625 625
 
626 626
 func (m *ClusterSpec) Reset()                    { *m = ClusterSpec{} }
627 627
 func (*ClusterSpec) ProtoMessage()               {}
628
-func (*ClusterSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{9} }
628
+func (*ClusterSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{10} }
629 629
 
630 630
 // SecretSpec specifies a user-provided secret.
631 631
 type SecretSpec struct {
... ...
@@ -636,7 +677,7 @@ type SecretSpec struct {
636 636
 
637 637
 func (m *SecretSpec) Reset()                    { *m = SecretSpec{} }
638 638
 func (*SecretSpec) ProtoMessage()               {}
639
-func (*SecretSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{10} }
639
+func (*SecretSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{11} }
640 640
 
641 641
 func init() {
642 642
 	proto.RegisterType((*NodeSpec)(nil), "docker.swarmkit.v1.NodeSpec")
... ...
@@ -644,6 +685,7 @@ func init() {
644 644
 	proto.RegisterType((*ReplicatedService)(nil), "docker.swarmkit.v1.ReplicatedService")
645 645
 	proto.RegisterType((*GlobalService)(nil), "docker.swarmkit.v1.GlobalService")
646 646
 	proto.RegisterType((*TaskSpec)(nil), "docker.swarmkit.v1.TaskSpec")
647
+	proto.RegisterType((*GenericRuntimeSpec)(nil), "docker.swarmkit.v1.GenericRuntimeSpec")
647 648
 	proto.RegisterType((*NetworkAttachmentSpec)(nil), "docker.swarmkit.v1.NetworkAttachmentSpec")
648 649
 	proto.RegisterType((*ContainerSpec)(nil), "docker.swarmkit.v1.ContainerSpec")
649 650
 	proto.RegisterType((*ContainerSpec_PullOptions)(nil), "docker.swarmkit.v1.ContainerSpec.PullOptions")
... ...
@@ -803,11 +845,36 @@ func (m *TaskSpec) CopyFrom(src interface{}) {
803 803
 			}
804 804
 			github_com_docker_swarmkit_api_deepcopy.Copy(v.Container, o.GetContainer())
805 805
 			m.Runtime = &v
806
+		case *TaskSpec_Generic:
807
+			v := TaskSpec_Generic{
808
+				Generic: &GenericRuntimeSpec{},
809
+			}
810
+			github_com_docker_swarmkit_api_deepcopy.Copy(v.Generic, o.GetGeneric())
811
+			m.Runtime = &v
806 812
 		}
807 813
 	}
808 814
 
809 815
 }
810 816
 
817
+func (m *GenericRuntimeSpec) Copy() *GenericRuntimeSpec {
818
+	if m == nil {
819
+		return nil
820
+	}
821
+	o := &GenericRuntimeSpec{}
822
+	o.CopyFrom(m)
823
+	return o
824
+}
825
+
826
+func (m *GenericRuntimeSpec) CopyFrom(src interface{}) {
827
+
828
+	o := src.(*GenericRuntimeSpec)
829
+	*m = *o
830
+	if o.Payload != nil {
831
+		m.Payload = &google_protobuf3.Any{}
832
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.Payload, o.Payload)
833
+	}
834
+}
835
+
811 836
 func (m *NetworkAttachmentSpec) Copy() *NetworkAttachmentSpec {
812 837
 	if m == nil {
813 838
 		return nil
... ...
@@ -1335,6 +1402,54 @@ func (m *TaskSpec_Attachment) MarshalTo(dAtA []byte) (int, error) {
1335 1335
 	}
1336 1336
 	return i, nil
1337 1337
 }
1338
+func (m *TaskSpec_Generic) MarshalTo(dAtA []byte) (int, error) {
1339
+	i := 0
1340
+	if m.Generic != nil {
1341
+		dAtA[i] = 0x52
1342
+		i++
1343
+		i = encodeVarintSpecs(dAtA, i, uint64(m.Generic.Size()))
1344
+		n17, err := m.Generic.MarshalTo(dAtA[i:])
1345
+		if err != nil {
1346
+			return 0, err
1347
+		}
1348
+		i += n17
1349
+	}
1350
+	return i, nil
1351
+}
1352
+func (m *GenericRuntimeSpec) Marshal() (dAtA []byte, err error) {
1353
+	size := m.Size()
1354
+	dAtA = make([]byte, size)
1355
+	n, err := m.MarshalTo(dAtA)
1356
+	if err != nil {
1357
+		return nil, err
1358
+	}
1359
+	return dAtA[:n], nil
1360
+}
1361
+
1362
+func (m *GenericRuntimeSpec) MarshalTo(dAtA []byte) (int, error) {
1363
+	var i int
1364
+	_ = i
1365
+	var l int
1366
+	_ = l
1367
+	if len(m.Kind) > 0 {
1368
+		dAtA[i] = 0xa
1369
+		i++
1370
+		i = encodeVarintSpecs(dAtA, i, uint64(len(m.Kind)))
1371
+		i += copy(dAtA[i:], m.Kind)
1372
+	}
1373
+	if m.Payload != nil {
1374
+		dAtA[i] = 0x12
1375
+		i++
1376
+		i = encodeVarintSpecs(dAtA, i, uint64(m.Payload.Size()))
1377
+		n18, err := m.Payload.MarshalTo(dAtA[i:])
1378
+		if err != nil {
1379
+			return 0, err
1380
+		}
1381
+		i += n18
1382
+	}
1383
+	return i, nil
1384
+}
1385
+
1338 1386
 func (m *NetworkAttachmentSpec) Marshal() (dAtA []byte, err error) {
1339 1387
 	size := m.Size()
1340 1388
 	dAtA = make([]byte, size)
... ...
@@ -1470,21 +1585,21 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
1470 1470
 		dAtA[i] = 0x4a
1471 1471
 		i++
1472 1472
 		i = encodeVarintSpecs(dAtA, i, uint64(m.StopGracePeriod.Size()))
1473
-		n17, err := m.StopGracePeriod.MarshalTo(dAtA[i:])
1473
+		n19, err := m.StopGracePeriod.MarshalTo(dAtA[i:])
1474 1474
 		if err != nil {
1475 1475
 			return 0, err
1476 1476
 		}
1477
-		i += n17
1477
+		i += n19
1478 1478
 	}
1479 1479
 	if m.PullOptions != nil {
1480 1480
 		dAtA[i] = 0x52
1481 1481
 		i++
1482 1482
 		i = encodeVarintSpecs(dAtA, i, uint64(m.PullOptions.Size()))
1483
-		n18, err := m.PullOptions.MarshalTo(dAtA[i:])
1483
+		n20, err := m.PullOptions.MarshalTo(dAtA[i:])
1484 1484
 		if err != nil {
1485 1485
 			return 0, err
1486 1486
 		}
1487
-		i += n18
1487
+		i += n20
1488 1488
 	}
1489 1489
 	if len(m.Groups) > 0 {
1490 1490
 		for _, s := range m.Groups {
... ...
@@ -1533,11 +1648,11 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
1533 1533
 		dAtA[i] = 0x7a
1534 1534
 		i++
1535 1535
 		i = encodeVarintSpecs(dAtA, i, uint64(m.DNSConfig.Size()))
1536
-		n19, err := m.DNSConfig.MarshalTo(dAtA[i:])
1536
+		n21, err := m.DNSConfig.MarshalTo(dAtA[i:])
1537 1537
 		if err != nil {
1538 1538
 			return 0, err
1539 1539
 		}
1540
-		i += n19
1540
+		i += n21
1541 1541
 	}
1542 1542
 	if m.Healthcheck != nil {
1543 1543
 		dAtA[i] = 0x82
... ...
@@ -1545,11 +1660,11 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
1545 1545
 		dAtA[i] = 0x1
1546 1546
 		i++
1547 1547
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Healthcheck.Size()))
1548
-		n20, err := m.Healthcheck.MarshalTo(dAtA[i:])
1548
+		n22, err := m.Healthcheck.MarshalTo(dAtA[i:])
1549 1549
 		if err != nil {
1550 1550
 			return 0, err
1551 1551
 		}
1552
-		i += n20
1552
+		i += n22
1553 1553
 	}
1554 1554
 	if len(m.Hosts) > 0 {
1555 1555
 		for _, s := range m.Hosts {
... ...
@@ -1745,20 +1860,20 @@ func (m *NetworkSpec) MarshalTo(dAtA []byte) (int, error) {
1745 1745
 	dAtA[i] = 0xa
1746 1746
 	i++
1747 1747
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
1748
-	n21, err := m.Annotations.MarshalTo(dAtA[i:])
1748
+	n23, err := m.Annotations.MarshalTo(dAtA[i:])
1749 1749
 	if err != nil {
1750 1750
 		return 0, err
1751 1751
 	}
1752
-	i += n21
1752
+	i += n23
1753 1753
 	if m.DriverConfig != nil {
1754 1754
 		dAtA[i] = 0x12
1755 1755
 		i++
1756 1756
 		i = encodeVarintSpecs(dAtA, i, uint64(m.DriverConfig.Size()))
1757
-		n22, err := m.DriverConfig.MarshalTo(dAtA[i:])
1757
+		n24, err := m.DriverConfig.MarshalTo(dAtA[i:])
1758 1758
 		if err != nil {
1759 1759
 			return 0, err
1760 1760
 		}
1761
-		i += n22
1761
+		i += n24
1762 1762
 	}
1763 1763
 	if m.Ipv6Enabled {
1764 1764
 		dAtA[i] = 0x18
... ...
@@ -1784,11 +1899,11 @@ func (m *NetworkSpec) MarshalTo(dAtA []byte) (int, error) {
1784 1784
 		dAtA[i] = 0x2a
1785 1785
 		i++
1786 1786
 		i = encodeVarintSpecs(dAtA, i, uint64(m.IPAM.Size()))
1787
-		n23, err := m.IPAM.MarshalTo(dAtA[i:])
1787
+		n25, err := m.IPAM.MarshalTo(dAtA[i:])
1788 1788
 		if err != nil {
1789 1789
 			return 0, err
1790 1790
 		}
1791
-		i += n23
1791
+		i += n25
1792 1792
 	}
1793 1793
 	if m.Attachable {
1794 1794
 		dAtA[i] = 0x30
... ...
@@ -1831,67 +1946,67 @@ func (m *ClusterSpec) MarshalTo(dAtA []byte) (int, error) {
1831 1831
 	dAtA[i] = 0xa
1832 1832
 	i++
1833 1833
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
1834
-	n24, err := m.Annotations.MarshalTo(dAtA[i:])
1834
+	n26, err := m.Annotations.MarshalTo(dAtA[i:])
1835 1835
 	if err != nil {
1836 1836
 		return 0, err
1837 1837
 	}
1838
-	i += n24
1838
+	i += n26
1839 1839
 	dAtA[i] = 0x12
1840 1840
 	i++
1841 1841
 	i = encodeVarintSpecs(dAtA, i, uint64(m.AcceptancePolicy.Size()))
1842
-	n25, err := m.AcceptancePolicy.MarshalTo(dAtA[i:])
1842
+	n27, err := m.AcceptancePolicy.MarshalTo(dAtA[i:])
1843 1843
 	if err != nil {
1844 1844
 		return 0, err
1845 1845
 	}
1846
-	i += n25
1846
+	i += n27
1847 1847
 	dAtA[i] = 0x1a
1848 1848
 	i++
1849 1849
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Orchestration.Size()))
1850
-	n26, err := m.Orchestration.MarshalTo(dAtA[i:])
1850
+	n28, err := m.Orchestration.MarshalTo(dAtA[i:])
1851 1851
 	if err != nil {
1852 1852
 		return 0, err
1853 1853
 	}
1854
-	i += n26
1854
+	i += n28
1855 1855
 	dAtA[i] = 0x22
1856 1856
 	i++
1857 1857
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Raft.Size()))
1858
-	n27, err := m.Raft.MarshalTo(dAtA[i:])
1858
+	n29, err := m.Raft.MarshalTo(dAtA[i:])
1859 1859
 	if err != nil {
1860 1860
 		return 0, err
1861 1861
 	}
1862
-	i += n27
1862
+	i += n29
1863 1863
 	dAtA[i] = 0x2a
1864 1864
 	i++
1865 1865
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Dispatcher.Size()))
1866
-	n28, err := m.Dispatcher.MarshalTo(dAtA[i:])
1866
+	n30, err := m.Dispatcher.MarshalTo(dAtA[i:])
1867 1867
 	if err != nil {
1868 1868
 		return 0, err
1869 1869
 	}
1870
-	i += n28
1870
+	i += n30
1871 1871
 	dAtA[i] = 0x32
1872 1872
 	i++
1873 1873
 	i = encodeVarintSpecs(dAtA, i, uint64(m.CAConfig.Size()))
1874
-	n29, err := m.CAConfig.MarshalTo(dAtA[i:])
1874
+	n31, err := m.CAConfig.MarshalTo(dAtA[i:])
1875 1875
 	if err != nil {
1876 1876
 		return 0, err
1877 1877
 	}
1878
-	i += n29
1878
+	i += n31
1879 1879
 	dAtA[i] = 0x3a
1880 1880
 	i++
1881 1881
 	i = encodeVarintSpecs(dAtA, i, uint64(m.TaskDefaults.Size()))
1882
-	n30, err := m.TaskDefaults.MarshalTo(dAtA[i:])
1882
+	n32, err := m.TaskDefaults.MarshalTo(dAtA[i:])
1883 1883
 	if err != nil {
1884 1884
 		return 0, err
1885 1885
 	}
1886
-	i += n30
1886
+	i += n32
1887 1887
 	dAtA[i] = 0x42
1888 1888
 	i++
1889 1889
 	i = encodeVarintSpecs(dAtA, i, uint64(m.EncryptionConfig.Size()))
1890
-	n31, err := m.EncryptionConfig.MarshalTo(dAtA[i:])
1890
+	n33, err := m.EncryptionConfig.MarshalTo(dAtA[i:])
1891 1891
 	if err != nil {
1892 1892
 		return 0, err
1893 1893
 	}
1894
-	i += n31
1894
+	i += n33
1895 1895
 	return i, nil
1896 1896
 }
1897 1897
 
... ...
@@ -1913,11 +2028,11 @@ func (m *SecretSpec) MarshalTo(dAtA []byte) (int, error) {
1913 1913
 	dAtA[i] = 0xa
1914 1914
 	i++
1915 1915
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
1916
-	n32, err := m.Annotations.MarshalTo(dAtA[i:])
1916
+	n34, err := m.Annotations.MarshalTo(dAtA[i:])
1917 1917
 	if err != nil {
1918 1918
 		return 0, err
1919 1919
 	}
1920
-	i += n32
1920
+	i += n34
1921 1921
 	if len(m.Data) > 0 {
1922 1922
 		dAtA[i] = 0x12
1923 1923
 		i++
... ...
@@ -2088,6 +2203,29 @@ func (m *TaskSpec_Attachment) Size() (n int) {
2088 2088
 	}
2089 2089
 	return n
2090 2090
 }
2091
+func (m *TaskSpec_Generic) Size() (n int) {
2092
+	var l int
2093
+	_ = l
2094
+	if m.Generic != nil {
2095
+		l = m.Generic.Size()
2096
+		n += 1 + l + sovSpecs(uint64(l))
2097
+	}
2098
+	return n
2099
+}
2100
+func (m *GenericRuntimeSpec) Size() (n int) {
2101
+	var l int
2102
+	_ = l
2103
+	l = len(m.Kind)
2104
+	if l > 0 {
2105
+		n += 1 + l + sovSpecs(uint64(l))
2106
+	}
2107
+	if m.Payload != nil {
2108
+		l = m.Payload.Size()
2109
+		n += 1 + l + sovSpecs(uint64(l))
2110
+	}
2111
+	return n
2112
+}
2113
+
2091 2114
 func (m *NetworkAttachmentSpec) Size() (n int) {
2092 2115
 	var l int
2093 2116
 	_ = l
... ...
@@ -2427,6 +2565,27 @@ func (this *TaskSpec_Attachment) String() string {
2427 2427
 	}, "")
2428 2428
 	return s
2429 2429
 }
2430
+func (this *TaskSpec_Generic) String() string {
2431
+	if this == nil {
2432
+		return "nil"
2433
+	}
2434
+	s := strings.Join([]string{`&TaskSpec_Generic{`,
2435
+		`Generic:` + strings.Replace(fmt.Sprintf("%v", this.Generic), "GenericRuntimeSpec", "GenericRuntimeSpec", 1) + `,`,
2436
+		`}`,
2437
+	}, "")
2438
+	return s
2439
+}
2440
+func (this *GenericRuntimeSpec) String() string {
2441
+	if this == nil {
2442
+		return "nil"
2443
+	}
2444
+	s := strings.Join([]string{`&GenericRuntimeSpec{`,
2445
+		`Kind:` + fmt.Sprintf("%v", this.Kind) + `,`,
2446
+		`Payload:` + strings.Replace(fmt.Sprintf("%v", this.Payload), "Any", "google_protobuf3.Any", 1) + `,`,
2447
+		`}`,
2448
+	}, "")
2449
+	return s
2450
+}
2430 2451
 func (this *NetworkAttachmentSpec) String() string {
2431 2452
 	if this == nil {
2432 2453
 		return "nil"
... ...
@@ -3396,6 +3555,150 @@ func (m *TaskSpec) Unmarshal(dAtA []byte) error {
3396 3396
 					break
3397 3397
 				}
3398 3398
 			}
3399
+		case 10:
3400
+			if wireType != 2 {
3401
+				return fmt.Errorf("proto: wrong wireType = %d for field Generic", wireType)
3402
+			}
3403
+			var msglen int
3404
+			for shift := uint(0); ; shift += 7 {
3405
+				if shift >= 64 {
3406
+					return ErrIntOverflowSpecs
3407
+				}
3408
+				if iNdEx >= l {
3409
+					return io.ErrUnexpectedEOF
3410
+				}
3411
+				b := dAtA[iNdEx]
3412
+				iNdEx++
3413
+				msglen |= (int(b) & 0x7F) << shift
3414
+				if b < 0x80 {
3415
+					break
3416
+				}
3417
+			}
3418
+			if msglen < 0 {
3419
+				return ErrInvalidLengthSpecs
3420
+			}
3421
+			postIndex := iNdEx + msglen
3422
+			if postIndex > l {
3423
+				return io.ErrUnexpectedEOF
3424
+			}
3425
+			v := &GenericRuntimeSpec{}
3426
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3427
+				return err
3428
+			}
3429
+			m.Runtime = &TaskSpec_Generic{v}
3430
+			iNdEx = postIndex
3431
+		default:
3432
+			iNdEx = preIndex
3433
+			skippy, err := skipSpecs(dAtA[iNdEx:])
3434
+			if err != nil {
3435
+				return err
3436
+			}
3437
+			if skippy < 0 {
3438
+				return ErrInvalidLengthSpecs
3439
+			}
3440
+			if (iNdEx + skippy) > l {
3441
+				return io.ErrUnexpectedEOF
3442
+			}
3443
+			iNdEx += skippy
3444
+		}
3445
+	}
3446
+
3447
+	if iNdEx > l {
3448
+		return io.ErrUnexpectedEOF
3449
+	}
3450
+	return nil
3451
+}
3452
+func (m *GenericRuntimeSpec) Unmarshal(dAtA []byte) error {
3453
+	l := len(dAtA)
3454
+	iNdEx := 0
3455
+	for iNdEx < l {
3456
+		preIndex := iNdEx
3457
+		var wire uint64
3458
+		for shift := uint(0); ; shift += 7 {
3459
+			if shift >= 64 {
3460
+				return ErrIntOverflowSpecs
3461
+			}
3462
+			if iNdEx >= l {
3463
+				return io.ErrUnexpectedEOF
3464
+			}
3465
+			b := dAtA[iNdEx]
3466
+			iNdEx++
3467
+			wire |= (uint64(b) & 0x7F) << shift
3468
+			if b < 0x80 {
3469
+				break
3470
+			}
3471
+		}
3472
+		fieldNum := int32(wire >> 3)
3473
+		wireType := int(wire & 0x7)
3474
+		if wireType == 4 {
3475
+			return fmt.Errorf("proto: GenericRuntimeSpec: wiretype end group for non-group")
3476
+		}
3477
+		if fieldNum <= 0 {
3478
+			return fmt.Errorf("proto: GenericRuntimeSpec: illegal tag %d (wire type %d)", fieldNum, wire)
3479
+		}
3480
+		switch fieldNum {
3481
+		case 1:
3482
+			if wireType != 2 {
3483
+				return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
3484
+			}
3485
+			var stringLen uint64
3486
+			for shift := uint(0); ; shift += 7 {
3487
+				if shift >= 64 {
3488
+					return ErrIntOverflowSpecs
3489
+				}
3490
+				if iNdEx >= l {
3491
+					return io.ErrUnexpectedEOF
3492
+				}
3493
+				b := dAtA[iNdEx]
3494
+				iNdEx++
3495
+				stringLen |= (uint64(b) & 0x7F) << shift
3496
+				if b < 0x80 {
3497
+					break
3498
+				}
3499
+			}
3500
+			intStringLen := int(stringLen)
3501
+			if intStringLen < 0 {
3502
+				return ErrInvalidLengthSpecs
3503
+			}
3504
+			postIndex := iNdEx + intStringLen
3505
+			if postIndex > l {
3506
+				return io.ErrUnexpectedEOF
3507
+			}
3508
+			m.Kind = string(dAtA[iNdEx:postIndex])
3509
+			iNdEx = postIndex
3510
+		case 2:
3511
+			if wireType != 2 {
3512
+				return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
3513
+			}
3514
+			var msglen int
3515
+			for shift := uint(0); ; shift += 7 {
3516
+				if shift >= 64 {
3517
+					return ErrIntOverflowSpecs
3518
+				}
3519
+				if iNdEx >= l {
3520
+					return io.ErrUnexpectedEOF
3521
+				}
3522
+				b := dAtA[iNdEx]
3523
+				iNdEx++
3524
+				msglen |= (int(b) & 0x7F) << shift
3525
+				if b < 0x80 {
3526
+					break
3527
+				}
3528
+			}
3529
+			if msglen < 0 {
3530
+				return ErrInvalidLengthSpecs
3531
+			}
3532
+			postIndex := iNdEx + msglen
3533
+			if postIndex > l {
3534
+				return io.ErrUnexpectedEOF
3535
+			}
3536
+			if m.Payload == nil {
3537
+				m.Payload = &google_protobuf3.Any{}
3538
+			}
3539
+			if err := m.Payload.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3540
+				return err
3541
+			}
3542
+			iNdEx = postIndex
3399 3543
 		default:
3400 3544
 			iNdEx = preIndex
3401 3545
 			skippy, err := skipSpecs(dAtA[iNdEx:])
... ...
@@ -5257,113 +5560,117 @@ var (
5257 5257
 func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) }
5258 5258
 
5259 5259
 var fileDescriptorSpecs = []byte{
5260
-	// 1717 bytes of a gzipped FileDescriptorProto
5261
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x41, 0x73, 0x1b, 0xb7,
5262
-	0x15, 0x16, 0x25, 0x8a, 0x5a, 0xbe, 0xa5, 0x6c, 0x1a, 0x75, 0xd2, 0x35, 0xdd, 0x50, 0x34, 0xe3,
5263
-	0xa6, 0x4a, 0x33, 0xa5, 0xa6, 0x6a, 0x27, 0x75, 0xea, 0x66, 0x5a, 0x52, 0x64, 0x65, 0x55, 0x95,
5264
-	0xcc, 0x01, 0x15, 0x77, 0x7c, 0xe2, 0x80, 0xbb, 0x10, 0xb9, 0xa3, 0xe5, 0x62, 0x0b, 0x60, 0x99,
5265
-	0xe1, 0xad, 0xc7, 0x8c, 0x0f, 0x3d, 0xf5, 0xaa, 0xe9, 0xa1, 0x7f, 0xc6, 0xb7, 0xf6, 0xd8, 0x93,
5266
-	0xa6, 0xe1, 0x5f, 0xe8, 0x0f, 0x68, 0x07, 0x58, 0x2c, 0xb9, 0x4c, 0x56, 0xb1, 0x67, 0xe2, 0x1b,
5267
-	0xde, 0xdb, 0xef, 0x7b, 0x00, 0x1e, 0x3e, 0x3c, 0xbc, 0x05, 0x5b, 0x44, 0xd4, 0x15, 0xad, 0x88,
5268
-	0x33, 0xc9, 0x10, 0xf2, 0x98, 0x7b, 0x45, 0x79, 0x4b, 0x7c, 0x49, 0xf8, 0xf4, 0xca, 0x97, 0xad,
5269
-	0xd9, 0xcf, 0x6b, 0xb6, 0x9c, 0x47, 0xd4, 0x00, 0x6a, 0xf7, 0xc7, 0x6c, 0xcc, 0xf4, 0xf0, 0x40,
5270
-	0x8d, 0x8c, 0xb7, 0x3e, 0x66, 0x6c, 0x1c, 0xd0, 0x03, 0x6d, 0x8d, 0xe2, 0xcb, 0x03, 0x2f, 0xe6,
5271
-	0x44, 0xfa, 0x2c, 0x4c, 0xbe, 0x37, 0xaf, 0x8b, 0x60, 0x9d, 0x33, 0x8f, 0x0e, 0x22, 0xea, 0xa2,
5272
-	0x63, 0xb0, 0x49, 0x18, 0x32, 0xa9, 0x01, 0xc2, 0x29, 0x34, 0x0a, 0xfb, 0xf6, 0xe1, 0x5e, 0xeb,
5273
-	0xdb, 0x33, 0xb7, 0xda, 0x2b, 0x58, 0xa7, 0xf8, 0xfa, 0x66, 0x6f, 0x03, 0x67, 0x99, 0xe8, 0xb7,
5274
-	0x50, 0xf1, 0xa8, 0xf0, 0x39, 0xf5, 0x86, 0x9c, 0x05, 0xd4, 0xd9, 0x6c, 0x14, 0xf6, 0xef, 0x1c,
5275
-	0xfe, 0x28, 0x2f, 0x92, 0x9a, 0x1c, 0xb3, 0x80, 0x62, 0xdb, 0x30, 0x94, 0x81, 0x8e, 0x01, 0xa6,
5276
-	0x74, 0x3a, 0xa2, 0x5c, 0x4c, 0xfc, 0xc8, 0xd9, 0xd2, 0xf4, 0x9f, 0xdc, 0x46, 0x57, 0x6b, 0x6f,
5277
-	0x9d, 0x2d, 0xe1, 0x38, 0x43, 0x45, 0x67, 0x50, 0x21, 0x33, 0xe2, 0x07, 0x64, 0xe4, 0x07, 0xbe,
5278
-	0x9c, 0x3b, 0x45, 0x1d, 0xea, 0xe3, 0xef, 0x0c, 0xd5, 0xce, 0x10, 0xf0, 0x1a, 0xbd, 0xe9, 0x01,
5279
-	0xac, 0x26, 0x42, 0x1f, 0xc1, 0x4e, 0xbf, 0x77, 0xde, 0x3d, 0x39, 0x3f, 0xae, 0x6e, 0xd4, 0x1e,
5280
-	0xbc, 0xba, 0x6e, 0xbc, 0xa7, 0x62, 0xac, 0x00, 0x7d, 0x1a, 0x7a, 0x7e, 0x38, 0x46, 0xfb, 0x60,
5281
-	0xb5, 0x8f, 0x8e, 0x7a, 0xfd, 0x8b, 0x5e, 0xb7, 0x5a, 0xa8, 0xd5, 0x5e, 0x5d, 0x37, 0xde, 0x5f,
5282
-	0x07, 0xb6, 0x5d, 0x97, 0x46, 0x92, 0x7a, 0xb5, 0xe2, 0x57, 0xff, 0xa8, 0x6f, 0x34, 0xbf, 0x2a,
5283
-	0x40, 0x25, 0xbb, 0x08, 0xf4, 0x11, 0x94, 0xda, 0x47, 0x17, 0x27, 0x2f, 0x7a, 0xd5, 0x8d, 0x15,
5284
-	0x3d, 0x8b, 0x68, 0xbb, 0xd2, 0x9f, 0x51, 0xf4, 0x18, 0xb6, 0xfb, 0xed, 0x2f, 0x06, 0xbd, 0x6a,
5285
-	0x61, 0xb5, 0x9c, 0x2c, 0xac, 0x4f, 0x62, 0xa1, 0x51, 0x5d, 0xdc, 0x3e, 0x39, 0xaf, 0x6e, 0xe6,
5286
-	0xa3, 0xba, 0x9c, 0xf8, 0xa1, 0x59, 0xca, 0xdf, 0x8b, 0x60, 0x0f, 0x28, 0x9f, 0xf9, 0xee, 0x3b,
5287
-	0x96, 0xc8, 0xa7, 0x50, 0x94, 0x44, 0x5c, 0x69, 0x69, 0xd8, 0xf9, 0xd2, 0xb8, 0x20, 0xe2, 0x4a,
5288
-	0x4d, 0x6a, 0xe8, 0x1a, 0xaf, 0x94, 0xc1, 0x69, 0x14, 0xf8, 0x2e, 0x91, 0xd4, 0xd3, 0xca, 0xb0,
5289
-	0x0f, 0x7f, 0x9c, 0xc7, 0xc6, 0x4b, 0x94, 0x59, 0xff, 0xb3, 0x0d, 0x9c, 0xa1, 0xa2, 0xa7, 0x50,
5290
-	0x1a, 0x07, 0x6c, 0x44, 0x02, 0xad, 0x09, 0xfb, 0xf0, 0x51, 0x5e, 0x90, 0x63, 0x8d, 0x58, 0x05,
5291
-	0x30, 0x14, 0xf4, 0x04, 0x4a, 0x71, 0xe4, 0x11, 0x49, 0x9d, 0x92, 0x26, 0x37, 0xf2, 0xc8, 0x5f,
5292
-	0x68, 0xc4, 0x11, 0x0b, 0x2f, 0xfd, 0x31, 0x36, 0x78, 0x74, 0x0a, 0x56, 0x48, 0xe5, 0x97, 0x8c,
5293
-	0x5f, 0x09, 0x67, 0xa7, 0xb1, 0xb5, 0x6f, 0x1f, 0x7e, 0x92, 0x2b, 0xc6, 0x04, 0xd3, 0x96, 0x92,
5294
-	0xb8, 0x93, 0x29, 0x0d, 0x65, 0x12, 0xa6, 0xb3, 0xe9, 0x14, 0xf0, 0x32, 0x00, 0xfa, 0x0d, 0x58,
5295
-	0x34, 0xf4, 0x22, 0xe6, 0x87, 0xd2, 0xb1, 0x6e, 0x5f, 0x48, 0xcf, 0x60, 0x54, 0x32, 0xf1, 0x92,
5296
-	0xa1, 0xd8, 0x9c, 0x05, 0xc1, 0x88, 0xb8, 0x57, 0x4e, 0xf9, 0x2d, 0xb7, 0xb1, 0x64, 0x74, 0x4a,
5297
-	0x50, 0x9c, 0x32, 0x8f, 0x36, 0x0f, 0xe0, 0xde, 0xb7, 0x52, 0x8d, 0x6a, 0x60, 0x99, 0x54, 0x27,
5298
-	0x1a, 0x29, 0xe2, 0xa5, 0xdd, 0xbc, 0x0b, 0xbb, 0x6b, 0x69, 0x6d, 0xfe, 0xb5, 0x08, 0x56, 0x7a,
5299
-	0xd6, 0xa8, 0x0d, 0x65, 0x97, 0x85, 0x92, 0xf8, 0x21, 0xe5, 0x46, 0x5e, 0xb9, 0x27, 0x73, 0x94,
5300
-	0x82, 0x14, 0xeb, 0xd9, 0x06, 0x5e, 0xb1, 0xd0, 0xef, 0xa1, 0xcc, 0xa9, 0x60, 0x31, 0x77, 0xa9,
5301
-	0x30, 0xfa, 0xda, 0xcf, 0x57, 0x48, 0x02, 0xc2, 0xf4, 0xcf, 0xb1, 0xcf, 0xa9, 0xca, 0xb2, 0xc0,
5302
-	0x2b, 0x2a, 0x7a, 0x0a, 0x3b, 0x9c, 0x0a, 0x49, 0xb8, 0xfc, 0x2e, 0x89, 0xe0, 0x04, 0xd2, 0x67,
5303
-	0x81, 0xef, 0xce, 0x71, 0xca, 0x40, 0x4f, 0xa1, 0x1c, 0x05, 0xc4, 0xd5, 0x51, 0x9d, 0x6d, 0x4d,
5304
-	0xff, 0x20, 0x8f, 0xde, 0x4f, 0x41, 0x78, 0x85, 0x47, 0x9f, 0x01, 0x04, 0x6c, 0x3c, 0xf4, 0xb8,
5305
-	0x3f, 0xa3, 0xdc, 0x48, 0xac, 0x96, 0xc7, 0xee, 0x6a, 0x04, 0x2e, 0x07, 0x6c, 0x9c, 0x0c, 0xd1,
5306
-	0xf1, 0xf7, 0xd2, 0x57, 0x46, 0x5b, 0xa7, 0x00, 0x64, 0xf9, 0xd5, 0xa8, 0xeb, 0xe3, 0xb7, 0x0a,
5307
-	0x65, 0x4e, 0x24, 0x43, 0x47, 0x8f, 0xa0, 0x72, 0xc9, 0xb8, 0x4b, 0x87, 0xe6, 0xd6, 0x94, 0xb5,
5308
-	0x26, 0x6c, 0xed, 0x4b, 0xf4, 0xd5, 0x29, 0xc3, 0x0e, 0x8f, 0x43, 0xe9, 0x4f, 0x69, 0xf3, 0x14,
5309
-	0xde, 0xcb, 0x0d, 0x8a, 0x0e, 0xa1, 0xb2, 0x3c, 0xe6, 0xa1, 0xef, 0x69, 0x7d, 0x94, 0x3b, 0x77,
5310
-	0x17, 0x37, 0x7b, 0xf6, 0x52, 0x0f, 0x27, 0x5d, 0x6c, 0x2f, 0x41, 0x27, 0x5e, 0xf3, 0x6f, 0x16,
5311
-	0xec, 0xae, 0x89, 0x05, 0xdd, 0x87, 0x6d, 0x7f, 0x4a, 0xc6, 0x34, 0xa1, 0xe3, 0xc4, 0x40, 0x3d,
5312
-	0x28, 0x05, 0x64, 0x44, 0x03, 0x25, 0x19, 0x95, 0xb6, 0x9f, 0xbd, 0x51, 0x75, 0xad, 0x3f, 0x6a,
5313
-	0x7c, 0x2f, 0x94, 0x7c, 0x8e, 0x0d, 0x19, 0x39, 0xb0, 0xe3, 0xb2, 0xe9, 0x94, 0x84, 0xaa, 0x38,
5314
-	0x6d, 0xed, 0x97, 0x71, 0x6a, 0x22, 0x04, 0x45, 0xc2, 0xc7, 0xc2, 0x29, 0x6a, 0xb7, 0x1e, 0xa3,
5315
-	0x2a, 0x6c, 0xd1, 0x70, 0xe6, 0x6c, 0x6b, 0x97, 0x1a, 0x2a, 0x8f, 0xe7, 0x27, 0x67, 0x5e, 0xc6,
5316
-	0x6a, 0xa8, 0x78, 0xb1, 0xa0, 0xdc, 0xd9, 0xd1, 0x2e, 0x3d, 0x46, 0xbf, 0x82, 0xd2, 0x94, 0xc5,
5317
-	0xa1, 0x14, 0x8e, 0xa5, 0x17, 0xfb, 0x20, 0x6f, 0xb1, 0x67, 0x0a, 0x61, 0x8a, 0xa7, 0x81, 0xa3,
5318
-	0x1e, 0xdc, 0x13, 0x92, 0x45, 0xc3, 0x31, 0x27, 0x2e, 0x1d, 0x46, 0x94, 0xfb, 0xcc, 0x33, 0x97,
5319
-	0xff, 0x41, 0x2b, 0xe9, 0x15, 0x5a, 0x69, 0xaf, 0xd0, 0xea, 0x9a, 0x5e, 0x01, 0xdf, 0x55, 0x9c,
5320
-	0x63, 0x45, 0xe9, 0x6b, 0x06, 0xea, 0x43, 0x25, 0x8a, 0x83, 0x60, 0xc8, 0xa2, 0xe4, 0x1d, 0x00,
5321
-	0x1d, 0xe1, 0x2d, 0x52, 0xd6, 0x8f, 0x83, 0xe0, 0x79, 0x42, 0xc2, 0x76, 0xb4, 0x32, 0xd0, 0xfb,
5322
-	0x50, 0x1a, 0x73, 0x16, 0x47, 0xc2, 0xb1, 0x75, 0x32, 0x8c, 0x85, 0x3e, 0x87, 0x1d, 0x41, 0x5d,
5323
-	0x4e, 0xa5, 0x70, 0x2a, 0x7a, 0xab, 0x1f, 0xe6, 0x4d, 0x32, 0xd0, 0x10, 0x4c, 0x2f, 0x29, 0xa7,
5324
-	0xa1, 0x4b, 0x71, 0xca, 0x41, 0x0f, 0x60, 0x4b, 0xca, 0xb9, 0xb3, 0xdb, 0x28, 0xec, 0x5b, 0x9d,
5325
-	0x9d, 0xc5, 0xcd, 0xde, 0xd6, 0xc5, 0xc5, 0x4b, 0xac, 0x7c, 0xaa, 0x46, 0x4d, 0x98, 0x90, 0x21,
5326
-	0x99, 0x52, 0xe7, 0x8e, 0xce, 0xed, 0xd2, 0x46, 0x2f, 0x01, 0xbc, 0x50, 0x0c, 0x5d, 0x7d, 0x29,
5327
-	0x9c, 0xbb, 0x7a, 0x77, 0x9f, 0xbc, 0x79, 0x77, 0xdd, 0xf3, 0x81, 0xa9, 0xd3, 0xbb, 0x8b, 0x9b,
5328
-	0xbd, 0xf2, 0xd2, 0xc4, 0x65, 0x2f, 0x14, 0xc9, 0x10, 0x75, 0xc0, 0x9e, 0x50, 0x12, 0xc8, 0x89,
5329
-	0x3b, 0xa1, 0xee, 0x95, 0x53, 0xbd, 0xbd, 0xf0, 0x3e, 0xd3, 0x30, 0x13, 0x21, 0x4b, 0x52, 0x0a,
5330
-	0x56, 0x4b, 0x15, 0xce, 0x3d, 0x9d, 0xab, 0xc4, 0x40, 0x1f, 0x00, 0xb0, 0x88, 0x86, 0x43, 0x21,
5331
-	0x3d, 0x3f, 0x74, 0x90, 0xda, 0x32, 0x2e, 0x2b, 0xcf, 0x40, 0x39, 0xd0, 0x43, 0x55, 0x16, 0x89,
5332
-	0x37, 0x64, 0x61, 0x30, 0x77, 0x7e, 0xa0, 0xbf, 0x5a, 0xca, 0xf1, 0x3c, 0x0c, 0xe6, 0x68, 0x0f,
5333
-	0x6c, 0xad, 0x0b, 0xe1, 0x8f, 0x43, 0x12, 0x38, 0xf7, 0x75, 0x3e, 0x40, 0xb9, 0x06, 0xda, 0x53,
5334
-	0xfb, 0x0c, 0xec, 0x8c, 0xdc, 0x95, 0x4c, 0xaf, 0xe8, 0xdc, 0xdc, 0x20, 0x35, 0x54, 0x6b, 0x9a,
5335
-	0x91, 0x20, 0x4e, 0x9a, 0xbd, 0x32, 0x4e, 0x8c, 0x5f, 0x6f, 0x3e, 0x29, 0xd4, 0x0e, 0xc1, 0xce,
5336
-	0x1c, 0x3b, 0xfa, 0x10, 0x76, 0x39, 0x1d, 0xfb, 0x42, 0xf2, 0xf9, 0x90, 0xc4, 0x72, 0xe2, 0xfc,
5337
-	0x4e, 0x13, 0x2a, 0xa9, 0xb3, 0x1d, 0xcb, 0x49, 0x6d, 0x08, 0xab, 0xec, 0xa1, 0x06, 0xd8, 0xea,
5338
-	0x54, 0x04, 0xe5, 0x33, 0xca, 0xd5, 0x83, 0xa2, 0x36, 0x9d, 0x75, 0x29, 0xf5, 0x08, 0x4a, 0xb8,
5339
-	0x3b, 0xd1, 0x97, 0xb7, 0x8c, 0x8d, 0xa5, 0x6e, 0x63, 0x2a, 0x51, 0x73, 0x1b, 0x8d, 0xd9, 0xfc,
5340
-	0x6f, 0x01, 0x2a, 0xd9, 0x77, 0x11, 0x1d, 0x25, 0xef, 0x99, 0xde, 0xd2, 0x9d, 0xc3, 0x83, 0x37,
5341
-	0xbd, 0xa3, 0xfa, 0xf5, 0x08, 0x62, 0x15, 0xec, 0x4c, 0xb5, 0xb0, 0x9a, 0x8c, 0x7e, 0x09, 0xdb,
5342
-	0x11, 0xe3, 0x32, 0xad, 0x21, 0xf5, 0xdc, 0x8a, 0xcf, 0x78, 0x5a, 0x6d, 0x13, 0x70, 0x73, 0x02,
5343
-	0x77, 0xd6, 0xa3, 0xa1, 0xc7, 0xb0, 0xf5, 0xe2, 0xa4, 0x5f, 0xdd, 0xa8, 0x3d, 0x7c, 0x75, 0xdd,
5344
-	0xf8, 0xe1, 0xfa, 0xc7, 0x17, 0x3e, 0x97, 0x31, 0x09, 0x4e, 0xfa, 0xe8, 0xa7, 0xb0, 0xdd, 0x3d,
5345
-	0x1f, 0x60, 0x5c, 0x2d, 0xd4, 0xf6, 0x5e, 0x5d, 0x37, 0x1e, 0xae, 0xe3, 0xd4, 0x27, 0x16, 0x87,
5346
-	0x1e, 0x66, 0xa3, 0x65, 0x3b, 0xf7, 0xcf, 0x4d, 0xb0, 0x4d, 0x69, 0x7d, 0xd7, 0x1d, 0xff, 0x6e,
5347
-	0xf2, 0x5a, 0xa5, 0x77, 0x66, 0xf3, 0x8d, 0x8f, 0x56, 0x25, 0x21, 0x98, 0x33, 0x7e, 0x04, 0x15,
5348
-	0x3f, 0x9a, 0x7d, 0x3a, 0xa4, 0x21, 0x19, 0x05, 0xa6, 0xb3, 0xb3, 0xb0, 0xad, 0x7c, 0xbd, 0xc4,
5349
-	0xa5, 0x2e, 0xac, 0x1f, 0x4a, 0xca, 0x43, 0xd3, 0xb3, 0x59, 0x78, 0x69, 0xa3, 0xcf, 0xa1, 0xe8,
5350
-	0x47, 0x64, 0x6a, 0x5e, 0xda, 0xdc, 0x1d, 0x9c, 0xf4, 0xdb, 0x67, 0x46, 0x83, 0x1d, 0x6b, 0x71,
5351
-	0xb3, 0x57, 0x54, 0x0e, 0xac, 0x69, 0xa8, 0x9e, 0x3e, 0x76, 0x6a, 0x26, 0x5d, 0x7c, 0x2d, 0x9c,
5352
-	0xf1, 0x28, 0x1d, 0xf9, 0xe1, 0x98, 0x53, 0x21, 0x74, 0x19, 0xb6, 0x70, 0x6a, 0x36, 0xff, 0x57,
5353
-	0x04, 0xfb, 0x28, 0x88, 0x85, 0x34, 0x8f, 0xcb, 0x3b, 0xcb, 0xe8, 0x4b, 0xb8, 0x47, 0xf4, 0x6f,
5354
-	0x01, 0x09, 0x55, 0xa5, 0xd6, 0xed, 0x85, 0xc9, 0xea, 0xe3, 0xdc, 0x70, 0x4b, 0x70, 0xd2, 0x8a,
5355
-	0x74, 0x4a, 0x2a, 0xa6, 0x53, 0xc0, 0x55, 0xf2, 0x8d, 0x2f, 0x68, 0x00, 0xbb, 0x8c, 0xbb, 0x13,
5356
-	0x2a, 0x64, 0x52, 0xdf, 0x4d, 0x1b, 0x9d, 0xfb, 0x83, 0xf5, 0x3c, 0x0b, 0x34, 0xc5, 0x2d, 0x59,
5357
-	0xed, 0x7a, 0x0c, 0xf4, 0x04, 0x8a, 0x9c, 0x5c, 0xa6, 0xad, 0x52, 0xae, 0xf2, 0x31, 0xb9, 0x94,
5358
-	0x6b, 0x21, 0x34, 0x03, 0xfd, 0x01, 0xc0, 0xf3, 0x45, 0x44, 0xa4, 0x3b, 0xa1, 0xdc, 0x9c, 0x60,
5359
-	0xee, 0x16, 0xbb, 0x4b, 0xd4, 0x5a, 0x94, 0x0c, 0x1b, 0x9d, 0x42, 0xd9, 0x25, 0xa9, 0x06, 0x4b,
5360
-	0xb7, 0xff, 0x5b, 0x1c, 0xb5, 0x4d, 0x88, 0xaa, 0x0a, 0xb1, 0xb8, 0xd9, 0xb3, 0x52, 0x0f, 0xb6,
5361
-	0x5c, 0x62, 0x34, 0x79, 0x0a, 0xbb, 0xea, 0x9f, 0x63, 0xe8, 0xd1, 0x4b, 0x12, 0x07, 0x32, 0x39,
5362
-	0xfb, 0x5b, 0x8a, 0xb5, 0x6a, 0x60, 0xbb, 0x06, 0x67, 0xd6, 0x55, 0x91, 0x19, 0x1f, 0xfa, 0x13,
5363
-	0xdc, 0xa3, 0xa1, 0xcb, 0xe7, 0x5a, 0x81, 0xe9, 0x0a, 0xad, 0xdb, 0x37, 0xdb, 0x5b, 0x82, 0xd7,
5364
-	0x36, 0x5b, 0xa5, 0xdf, 0xf0, 0x37, 0x7d, 0x80, 0xe4, 0xf9, 0x7b, 0xb7, 0xfa, 0x43, 0x50, 0xf4,
5365
-	0x88, 0x24, 0x5a, 0x72, 0x15, 0xac, 0xc7, 0x1d, 0xe7, 0xf5, 0xd7, 0xf5, 0x8d, 0x7f, 0x7f, 0x5d,
5366
-	0xdf, 0xf8, 0xcb, 0xa2, 0x5e, 0x78, 0xbd, 0xa8, 0x17, 0xfe, 0xb5, 0xa8, 0x17, 0xfe, 0xb3, 0xa8,
5367
-	0x17, 0x46, 0x25, 0xdd, 0x34, 0xfc, 0xe2, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x64, 0x44, 0x1e,
5368
-	0x4f, 0xb4, 0x10, 0x00, 0x00,
5260
+	// 1779 bytes of a gzipped FileDescriptorProto
5261
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x41, 0x73, 0x1b, 0x49,
5262
+	0x15, 0xb6, 0x6c, 0x59, 0x1a, 0xbd, 0x91, 0x13, 0xb9, 0xc9, 0x2e, 0x63, 0x85, 0x95, 0x15, 0x6d,
5263
+	0x08, 0x5e, 0xb6, 0x90, 0x0b, 0x43, 0x2d, 0x59, 0xc2, 0x16, 0x48, 0x96, 0x70, 0x8c, 0xb1, 0xa3,
5264
+	0x6a, 0x7b, 0x03, 0x39, 0xa9, 0xda, 0x33, 0x6d, 0x69, 0xca, 0xa3, 0xee, 0xa1, 0xa7, 0xc7, 0x5b,
5265
+	0xba, 0x71, 0xdc, 0xca, 0x99, 0xab, 0x8b, 0x03, 0x7f, 0x26, 0x37, 0x28, 0x4e, 0x9c, 0x5c, 0xac,
5266
+	0xfe, 0x02, 0x3f, 0x00, 0xaa, 0x7b, 0x7a, 0xa4, 0x51, 0x32, 0x4e, 0x52, 0x45, 0x6e, 0xfd, 0x5e,
5267
+	0x7f, 0xdf, 0x9b, 0xd7, 0xaf, 0xbf, 0xee, 0xd7, 0x03, 0x76, 0x14, 0x52, 0x37, 0x6a, 0x87, 0x82,
5268
+	0x4b, 0x8e, 0x90, 0xc7, 0xdd, 0x4b, 0x2a, 0xda, 0xd1, 0x37, 0x44, 0x4c, 0x2e, 0x7d, 0xd9, 0xbe,
5269
+	0xfa, 0x69, 0xdd, 0x96, 0xd3, 0x90, 0x1a, 0x40, 0xfd, 0xde, 0x88, 0x8f, 0xb8, 0x1e, 0xee, 0xaa,
5270
+	0x91, 0xf1, 0x36, 0x46, 0x9c, 0x8f, 0x02, 0xba, 0xab, 0xad, 0xf3, 0xf8, 0x62, 0xd7, 0x8b, 0x05,
5271
+	0x91, 0x3e, 0x67, 0x66, 0x7e, 0xeb, 0xf5, 0x79, 0xc2, 0xa6, 0xc9, 0x54, 0xeb, 0xba, 0x08, 0xd6,
5272
+	0x09, 0xf7, 0xe8, 0x69, 0x48, 0x5d, 0x74, 0x00, 0x36, 0x61, 0x8c, 0x4b, 0xcd, 0x8d, 0x9c, 0x42,
5273
+	0xb3, 0xb0, 0x63, 0xef, 0x6d, 0xb7, 0xdf, 0x4c, 0xaa, 0xdd, 0x59, 0xc0, 0xba, 0xc5, 0x57, 0x37,
5274
+	0xdb, 0x2b, 0x38, 0xcb, 0x44, 0xbf, 0x86, 0xaa, 0x47, 0x23, 0x5f, 0x50, 0x6f, 0x28, 0x78, 0x40,
5275
+	0x9d, 0xd5, 0x66, 0x61, 0xe7, 0xce, 0xde, 0x0f, 0xf2, 0x22, 0xa9, 0x8f, 0x63, 0x1e, 0x50, 0x6c,
5276
+	0x1b, 0x86, 0x32, 0xd0, 0x01, 0xc0, 0x84, 0x4e, 0xce, 0xa9, 0x88, 0xc6, 0x7e, 0xe8, 0xac, 0x69,
5277
+	0xfa, 0x8f, 0x6e, 0xa3, 0xab, 0xdc, 0xdb, 0xc7, 0x73, 0x38, 0xce, 0x50, 0xd1, 0x31, 0x54, 0xc9,
5278
+	0x15, 0xf1, 0x03, 0x72, 0xee, 0x07, 0xbe, 0x9c, 0x3a, 0x45, 0x1d, 0xea, 0xb3, 0xb7, 0x86, 0xea,
5279
+	0x64, 0x08, 0x78, 0x89, 0xde, 0xf2, 0x00, 0x16, 0x1f, 0x42, 0x8f, 0xa0, 0x3c, 0xe8, 0x9f, 0xf4,
5280
+	0x0e, 0x4f, 0x0e, 0x6a, 0x2b, 0xf5, 0xad, 0x97, 0xd7, 0xcd, 0x8f, 0x54, 0x8c, 0x05, 0x60, 0x40,
5281
+	0x99, 0xe7, 0xb3, 0x11, 0xda, 0x01, 0xab, 0xb3, 0xbf, 0xdf, 0x1f, 0x9c, 0xf5, 0x7b, 0xb5, 0x42,
5282
+	0xbd, 0xfe, 0xf2, 0xba, 0xf9, 0xf1, 0x32, 0xb0, 0xe3, 0xba, 0x34, 0x94, 0xd4, 0xab, 0x17, 0xbf,
5283
+	0xfd, 0x5b, 0x63, 0xa5, 0xf5, 0x6d, 0x01, 0xaa, 0xd9, 0x24, 0xd0, 0x23, 0x28, 0x75, 0xf6, 0xcf,
5284
+	0x0e, 0x9f, 0xf7, 0x6b, 0x2b, 0x0b, 0x7a, 0x16, 0xd1, 0x71, 0xa5, 0x7f, 0x45, 0xd1, 0x43, 0x58,
5285
+	0x1f, 0x74, 0xbe, 0x3e, 0xed, 0xd7, 0x0a, 0x8b, 0x74, 0xb2, 0xb0, 0x01, 0x89, 0x23, 0x8d, 0xea,
5286
+	0xe1, 0xce, 0xe1, 0x49, 0x6d, 0x35, 0x1f, 0xd5, 0x13, 0xc4, 0x67, 0x26, 0x95, 0xbf, 0x16, 0xc1,
5287
+	0x3e, 0xa5, 0xe2, 0xca, 0x77, 0x3f, 0xb0, 0x44, 0xbe, 0x80, 0xa2, 0x24, 0xd1, 0xa5, 0x96, 0x86,
5288
+	0x9d, 0x2f, 0x8d, 0x33, 0x12, 0x5d, 0xaa, 0x8f, 0x1a, 0xba, 0xc6, 0x2b, 0x65, 0x08, 0x1a, 0x06,
5289
+	0xbe, 0x4b, 0x24, 0xf5, 0xb4, 0x32, 0xec, 0xbd, 0x1f, 0xe6, 0xb1, 0xf1, 0x1c, 0x65, 0xf2, 0x7f,
5290
+	0xba, 0x82, 0x33, 0x54, 0xf4, 0x04, 0x4a, 0xa3, 0x80, 0x9f, 0x93, 0x40, 0x6b, 0xc2, 0xde, 0x7b,
5291
+	0x90, 0x17, 0xe4, 0x40, 0x23, 0x16, 0x01, 0x0c, 0x05, 0x3d, 0x86, 0x52, 0x1c, 0x7a, 0x44, 0x52,
5292
+	0xa7, 0xa4, 0xc9, 0xcd, 0x3c, 0xf2, 0xd7, 0x1a, 0xb1, 0xcf, 0xd9, 0x85, 0x3f, 0xc2, 0x06, 0x8f,
5293
+	0x8e, 0xc0, 0x62, 0x54, 0x7e, 0xc3, 0xc5, 0x65, 0xe4, 0x94, 0x9b, 0x6b, 0x3b, 0xf6, 0xde, 0xe7,
5294
+	0xb9, 0x62, 0x4c, 0x30, 0x1d, 0x29, 0x89, 0x3b, 0x9e, 0x50, 0x26, 0x93, 0x30, 0xdd, 0x55, 0xa7,
5295
+	0x80, 0xe7, 0x01, 0xd0, 0xaf, 0xc0, 0xa2, 0xcc, 0x0b, 0xb9, 0xcf, 0xa4, 0x63, 0xdd, 0x9e, 0x48,
5296
+	0xdf, 0x60, 0x54, 0x31, 0xf1, 0x9c, 0xa1, 0xd8, 0x82, 0x07, 0xc1, 0x39, 0x71, 0x2f, 0x9d, 0xca,
5297
+	0x7b, 0x2e, 0x63, 0xce, 0xe8, 0x96, 0xa0, 0x38, 0xe1, 0x1e, 0x6d, 0xed, 0xc2, 0xe6, 0x1b, 0xa5,
5298
+	0x46, 0x75, 0xb0, 0x4c, 0xa9, 0x13, 0x8d, 0x14, 0xf1, 0xdc, 0x6e, 0xdd, 0x85, 0x8d, 0xa5, 0xb2,
5299
+	0xb6, 0xfe, 0x59, 0x04, 0x2b, 0xdd, 0x6b, 0xd4, 0x81, 0x8a, 0xcb, 0x99, 0x24, 0x3e, 0xa3, 0xc2,
5300
+	0xc8, 0x2b, 0x77, 0x67, 0xf6, 0x53, 0x90, 0x62, 0x3d, 0x5d, 0xc1, 0x0b, 0x16, 0xfa, 0x2d, 0x54,
5301
+	0x04, 0x8d, 0x78, 0x2c, 0x5c, 0x1a, 0x19, 0x7d, 0xed, 0xe4, 0x2b, 0x24, 0x01, 0x61, 0xfa, 0xa7,
5302
+	0xd8, 0x17, 0x54, 0x55, 0x39, 0xc2, 0x0b, 0x2a, 0x7a, 0x02, 0x65, 0x41, 0x23, 0x49, 0x84, 0x7c,
5303
+	0x9b, 0x44, 0x70, 0x02, 0x19, 0xf0, 0xc0, 0x77, 0xa7, 0x38, 0x65, 0xa0, 0x27, 0x50, 0x09, 0x03,
5304
+	0xe2, 0xea, 0xa8, 0xce, 0xba, 0xa6, 0x7f, 0x92, 0x47, 0x1f, 0xa4, 0x20, 0xbc, 0xc0, 0xa3, 0x2f,
5305
+	0x01, 0x02, 0x3e, 0x1a, 0x7a, 0xc2, 0xbf, 0xa2, 0xc2, 0x48, 0xac, 0x9e, 0xc7, 0xee, 0x69, 0x04,
5306
+	0xae, 0x04, 0x7c, 0x94, 0x0c, 0xd1, 0xc1, 0xff, 0xa5, 0xaf, 0x8c, 0xb6, 0x8e, 0x00, 0xc8, 0x7c,
5307
+	0xd6, 0xa8, 0xeb, 0xb3, 0xf7, 0x0a, 0x65, 0x76, 0x24, 0x43, 0x47, 0x0f, 0xa0, 0x7a, 0xc1, 0x85,
5308
+	0x4b, 0x87, 0xe6, 0xd4, 0x54, 0xb4, 0x26, 0x6c, 0xed, 0x4b, 0xf4, 0x85, 0xba, 0x50, 0x1e, 0x51,
5309
+	0x46, 0x85, 0xef, 0x3a, 0xa0, 0x3f, 0xf6, 0x28, 0xf7, 0x40, 0x26, 0x10, 0x1c, 0x33, 0xe9, 0x4f,
5310
+	0xa8, 0xf9, 0x52, 0x4a, 0xec, 0x56, 0xa0, 0x2c, 0x92, 0x99, 0xd6, 0x1f, 0x01, 0xbd, 0x89, 0x45,
5311
+	0x08, 0x8a, 0x97, 0x3e, 0xf3, 0xb4, 0xb0, 0x2a, 0x58, 0x8f, 0x51, 0x1b, 0xca, 0x21, 0x99, 0x06,
5312
+	0x9c, 0x78, 0x46, 0x2c, 0xf7, 0xda, 0x49, 0xbf, 0x6c, 0xa7, 0xfd, 0xb2, 0xdd, 0x61, 0x53, 0x9c,
5313
+	0x82, 0x5a, 0x47, 0xf0, 0x51, 0xee, 0x92, 0xd1, 0x1e, 0x54, 0xe7, 0x22, 0x1c, 0xfa, 0xe6, 0x23,
5314
+	0xdd, 0xbb, 0xb3, 0x9b, 0x6d, 0x7b, 0xae, 0xd6, 0xc3, 0x1e, 0xb6, 0xe7, 0xa0, 0x43, 0xaf, 0xf5,
5315
+	0x17, 0x0b, 0x36, 0x96, 0xa4, 0x8c, 0xee, 0xc1, 0xba, 0x3f, 0x21, 0x23, 0x6a, 0x72, 0x4c, 0x0c,
5316
+	0xd4, 0x87, 0x52, 0x40, 0xce, 0x69, 0xa0, 0x04, 0xad, 0x36, 0xf5, 0x27, 0xef, 0x3c, 0x13, 0xed,
5317
+	0xdf, 0x6b, 0x7c, 0x9f, 0x49, 0x31, 0xc5, 0x86, 0x8c, 0x1c, 0x28, 0xbb, 0x7c, 0x32, 0x21, 0x4c,
5318
+	0x5d, 0x9d, 0x6b, 0x3b, 0x15, 0x9c, 0x9a, 0xaa, 0x32, 0x44, 0x8c, 0x22, 0xa7, 0xa8, 0xdd, 0x7a,
5319
+	0x8c, 0x6a, 0xb0, 0x46, 0xd9, 0x95, 0xb3, 0xae, 0x5d, 0x6a, 0xa8, 0x3c, 0x9e, 0x9f, 0x28, 0xb2,
5320
+	0x82, 0xd5, 0x50, 0xf1, 0xe2, 0x88, 0x0a, 0xa7, 0x9c, 0x54, 0x54, 0x8d, 0xd1, 0x2f, 0xa0, 0x34,
5321
+	0xe1, 0x31, 0x93, 0x91, 0x63, 0xe9, 0x64, 0xb7, 0xf2, 0x92, 0x3d, 0x56, 0x08, 0x73, 0xb5, 0x1b,
5322
+	0x38, 0xea, 0xc3, 0x66, 0x24, 0x79, 0x38, 0x1c, 0x09, 0xe2, 0xd2, 0x61, 0x48, 0x85, 0xcf, 0x3d,
5323
+	0x73, 0x35, 0x6d, 0xbd, 0xb1, 0x29, 0x3d, 0xf3, 0xc8, 0xc1, 0x77, 0x15, 0xe7, 0x40, 0x51, 0x06,
5324
+	0x9a, 0x81, 0x06, 0x50, 0x0d, 0xe3, 0x20, 0x18, 0xf2, 0x30, 0xe9, 0x52, 0x89, 0x9e, 0xde, 0xa3,
5325
+	0x64, 0x83, 0x38, 0x08, 0x9e, 0x25, 0x24, 0x6c, 0x87, 0x0b, 0x03, 0x7d, 0x0c, 0xa5, 0x91, 0xe0,
5326
+	0x71, 0x18, 0x39, 0xb6, 0x2e, 0x86, 0xb1, 0xd0, 0x57, 0x50, 0x8e, 0xa8, 0x2b, 0xa8, 0x8c, 0x9c,
5327
+	0xaa, 0x5e, 0xea, 0xa7, 0x79, 0x1f, 0x39, 0xd5, 0x10, 0x4c, 0x2f, 0xa8, 0xa0, 0xcc, 0xa5, 0x38,
5328
+	0xe5, 0xa0, 0x2d, 0x58, 0x93, 0x72, 0xea, 0x6c, 0x34, 0x0b, 0x3b, 0x56, 0xb7, 0x3c, 0xbb, 0xd9,
5329
+	0x5e, 0x3b, 0x3b, 0x7b, 0x81, 0x95, 0x4f, 0xdd, 0xa0, 0x63, 0x1e, 0x49, 0x46, 0x26, 0xd4, 0xb9,
5330
+	0xa3, 0x6b, 0x3b, 0xb7, 0xd1, 0x0b, 0x00, 0x8f, 0x45, 0x43, 0x57, 0x1f, 0x59, 0xe7, 0xae, 0x5e,
5331
+	0xdd, 0xe7, 0xef, 0x5e, 0x5d, 0xef, 0xe4, 0xd4, 0x74, 0x91, 0x8d, 0xd9, 0xcd, 0x76, 0x65, 0x6e,
5332
+	0xe2, 0x8a, 0xc7, 0xa2, 0x64, 0x88, 0xba, 0x60, 0x8f, 0x29, 0x09, 0xe4, 0xd8, 0x1d, 0x53, 0xf7,
5333
+	0xd2, 0xa9, 0xdd, 0xde, 0x16, 0x9e, 0x6a, 0x98, 0x89, 0x90, 0x25, 0x29, 0x05, 0xab, 0x54, 0x23,
5334
+	0x67, 0x53, 0xd7, 0x2a, 0x31, 0xd0, 0x27, 0x00, 0x3c, 0xa4, 0x6c, 0x18, 0x49, 0xcf, 0x67, 0x0e,
5335
+	0x52, 0x4b, 0xc6, 0x15, 0xe5, 0x39, 0x55, 0x0e, 0x74, 0x5f, 0x5d, 0xda, 0xc4, 0x1b, 0x72, 0x16,
5336
+	0x4c, 0x9d, 0xef, 0xe9, 0x59, 0x4b, 0x39, 0x9e, 0xb1, 0x60, 0x8a, 0xb6, 0xc1, 0xd6, 0xba, 0x88,
5337
+	0xfc, 0x11, 0x23, 0x81, 0x73, 0x4f, 0xd7, 0x03, 0x94, 0xeb, 0x54, 0x7b, 0xea, 0x5f, 0x82, 0x9d,
5338
+	0x91, 0xbb, 0x92, 0xe9, 0x25, 0x9d, 0x9a, 0x13, 0xa4, 0x86, 0x2a, 0xa7, 0x2b, 0x12, 0xc4, 0xc9,
5339
+	0x53, 0xb4, 0x82, 0x13, 0xe3, 0x97, 0xab, 0x8f, 0x0b, 0xf5, 0x3d, 0xb0, 0x33, 0xdb, 0x8e, 0x3e,
5340
+	0x85, 0x0d, 0x41, 0x47, 0x7e, 0x24, 0xc5, 0x74, 0x48, 0x62, 0x39, 0x76, 0x7e, 0xa3, 0x09, 0xd5,
5341
+	0xd4, 0xd9, 0x89, 0xe5, 0xb8, 0x3e, 0x84, 0x45, 0xf5, 0x50, 0x13, 0x6c, 0xb5, 0x2b, 0x11, 0x15,
5342
+	0x57, 0x54, 0xa8, 0x76, 0xa7, 0x16, 0x9d, 0x75, 0x29, 0xf5, 0x44, 0x94, 0x08, 0x77, 0xac, 0x0f,
5343
+	0x6f, 0x05, 0x1b, 0x4b, 0x9d, 0xc6, 0x54, 0xa2, 0xe6, 0x34, 0x1a, 0xb3, 0xf5, 0x9f, 0x02, 0x54,
5344
+	0xb3, 0x5d, 0x1b, 0xed, 0x27, 0xdd, 0x56, 0x2f, 0xe9, 0xce, 0xde, 0xee, 0xbb, 0xba, 0xbc, 0xee,
5345
+	0x6d, 0x41, 0xac, 0x82, 0x1d, 0xab, 0x07, 0xb6, 0x26, 0xa3, 0x9f, 0xc3, 0x7a, 0xc8, 0x85, 0x4c,
5346
+	0xef, 0x90, 0x46, 0x6e, 0x3f, 0xe2, 0x22, 0xed, 0x05, 0x09, 0xb8, 0x35, 0x86, 0x3b, 0xcb, 0xd1,
5347
+	0xd0, 0x43, 0x58, 0x7b, 0x7e, 0x38, 0xa8, 0xad, 0xd4, 0xef, 0xbf, 0xbc, 0x6e, 0x7e, 0x7f, 0x79,
5348
+	0xf2, 0xb9, 0x2f, 0x64, 0x4c, 0x82, 0xc3, 0x01, 0xfa, 0x31, 0xac, 0xf7, 0x4e, 0x4e, 0x31, 0xae,
5349
+	0x15, 0xea, 0xdb, 0x2f, 0xaf, 0x9b, 0xf7, 0x97, 0x71, 0x6a, 0x8a, 0xc7, 0xcc, 0xc3, 0xfc, 0x7c,
5350
+	0xfe, 0xd8, 0xfc, 0xfb, 0x2a, 0xd8, 0xe6, 0x6a, 0xfd, 0xd0, 0xff, 0x23, 0x1b, 0x49, 0x2f, 0x4d,
5351
+	0xcf, 0xcc, 0xea, 0x3b, 0x5b, 0x6a, 0x35, 0x21, 0x98, 0x3d, 0x7e, 0x00, 0x55, 0x3f, 0xbc, 0xfa,
5352
+	0x62, 0x48, 0x19, 0x39, 0x0f, 0xcc, 0xbb, 0xd3, 0xc2, 0xb6, 0xf2, 0xf5, 0x13, 0x97, 0x3a, 0xb0,
5353
+	0x3e, 0x93, 0x54, 0x30, 0xf3, 0xa2, 0xb4, 0xf0, 0xdc, 0x46, 0x5f, 0x41, 0xd1, 0x0f, 0xc9, 0xc4,
5354
+	0xbc, 0x03, 0x72, 0x57, 0x70, 0x38, 0xe8, 0x1c, 0x1b, 0x0d, 0x76, 0xad, 0xd9, 0xcd, 0x76, 0x51,
5355
+	0x39, 0xb0, 0xa6, 0xa1, 0x46, 0xda, 0x8a, 0xd5, 0x97, 0xf4, 0xe5, 0x6b, 0xe1, 0x8c, 0x47, 0xe9,
5356
+	0xc8, 0x67, 0x23, 0x41, 0xa3, 0x48, 0x5f, 0xc3, 0x16, 0x4e, 0xcd, 0xd6, 0x7f, 0x8b, 0x60, 0xef,
5357
+	0x07, 0x71, 0x24, 0x4d, 0x73, 0xf9, 0x60, 0x15, 0x7d, 0x01, 0x9b, 0x44, 0xff, 0xb4, 0x10, 0xa6,
5358
+	0x6e, 0x6a, 0xfd, 0xf8, 0x31, 0x55, 0x7d, 0x98, 0x1b, 0x6e, 0x0e, 0x4e, 0x1e, 0x4a, 0xdd, 0x92,
5359
+	0x8a, 0xe9, 0x14, 0x70, 0x8d, 0xbc, 0x36, 0x83, 0x4e, 0x61, 0x83, 0x0b, 0x77, 0x4c, 0x23, 0x99,
5360
+	0xdc, 0xef, 0xe6, 0x91, 0x9f, 0xfb, 0xfb, 0xf7, 0x2c, 0x0b, 0x34, 0x97, 0x5b, 0x92, 0xed, 0x72,
5361
+	0x0c, 0xf4, 0x18, 0x8a, 0x82, 0x5c, 0xa4, 0x0f, 0xb9, 0x5c, 0xe5, 0x63, 0x72, 0x21, 0x97, 0x42,
5362
+	0x68, 0x06, 0xfa, 0x1d, 0x80, 0xe7, 0x47, 0x21, 0x91, 0xee, 0x98, 0x0a, 0xb3, 0x83, 0xb9, 0x4b,
5363
+	0xec, 0xcd, 0x51, 0x4b, 0x51, 0x32, 0x6c, 0x74, 0x04, 0x15, 0x97, 0xa4, 0x1a, 0x2c, 0xdd, 0xfe,
5364
+	0xe7, 0xb3, 0xdf, 0x31, 0x21, 0x6a, 0x2a, 0xc4, 0xec, 0x66, 0xdb, 0x4a, 0x3d, 0xd8, 0x72, 0x89,
5365
+	0xd1, 0xe4, 0x11, 0x6c, 0xa8, 0x3f, 0xa2, 0xa1, 0x47, 0x2f, 0x48, 0x1c, 0xc8, 0x64, 0xef, 0x6f,
5366
+	0xb9, 0xac, 0xd5, 0xf3, 0xba, 0x67, 0x70, 0x26, 0xaf, 0xaa, 0xcc, 0xf8, 0xd0, 0x1f, 0x60, 0x93,
5367
+	0x32, 0x57, 0x4c, 0xb5, 0x02, 0xd3, 0x0c, 0xad, 0xdb, 0x17, 0xdb, 0x9f, 0x83, 0x97, 0x16, 0x5b,
5368
+	0xa3, 0xaf, 0xf9, 0x5b, 0x3e, 0x40, 0xd2, 0xfe, 0x3e, 0xac, 0xfe, 0x10, 0x14, 0x3d, 0x22, 0x89,
5369
+	0x96, 0x5c, 0x15, 0xeb, 0x71, 0xd7, 0x79, 0xf5, 0x5d, 0x63, 0xe5, 0x5f, 0xdf, 0x35, 0x56, 0xfe,
5370
+	0x3c, 0x6b, 0x14, 0x5e, 0xcd, 0x1a, 0x85, 0x7f, 0xcc, 0x1a, 0x85, 0x7f, 0xcf, 0x1a, 0x85, 0xf3,
5371
+	0x92, 0x7e, 0x34, 0xfc, 0xec, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbe, 0x3e, 0xe8, 0xcb, 0x6d,
5372
+	0x11, 0x00, 0x00,
5369 5373
 }
... ...
@@ -5,6 +5,7 @@ package docker.swarmkit.v1;
5 5
 import "types.proto";
6 6
 import "gogoproto/gogo.proto";
7 7
 import "google/protobuf/duration.proto";
8
+import "google/protobuf/any.proto";
8 9
 
9 10
 // Specs are container objects for user provided input. All creations and
10 11
 // updates are done through spec types. As a convention, user input from a spec
... ...
@@ -101,6 +102,7 @@ message TaskSpec {
101 101
 	oneof runtime {
102 102
 		NetworkAttachmentSpec attachment = 8;
103 103
 		ContainerSpec container = 1;
104
+		GenericRuntimeSpec generic = 10;
104 105
 	}
105 106
 
106 107
 	// Resource requirements for the container.
... ...
@@ -128,6 +130,11 @@ message TaskSpec {
128 128
 	uint64 force_update = 9;
129 129
 }
130 130
 
131
+message GenericRuntimeSpec {
132
+	string kind = 1;
133
+	google.protobuf.Any payload = 2;
134
+}
135
+
131 136
 // NetworkAttachmentSpec specifies runtime parameters required to attach
132 137
 // a container to a network.
133 138
 message NetworkAttachmentSpec {
... ...
@@ -321,7 +328,7 @@ message NetworkSpec {
321 321
 	// enabled(default case) no manual attachment to this network
322 322
 	// can happen.
323 323
 	bool attachable = 6;
324
-	
324
+
325 325
 	// Ingress indicates this network will provide the routing-mesh.
326 326
 	// In older versions, the network providing the routing mesh was
327 327
 	// swarm internally created only and it was identified by the name
328 328
new file mode 100644
... ...
@@ -0,0 +1,80 @@
0
+package api
1
+
2
+import (
3
+	"errors"
4
+	"fmt"
5
+
6
+	"github.com/docker/go-events"
7
+)
8
+
9
+var errUnknownStoreAction = errors.New("unrecognized action type")
10
+
11
+// StoreObject is an abstract object that can be handled by the store.
12
+type StoreObject interface {
13
+	GetID() string                // Get ID
14
+	GetMeta() Meta                // Retrieve metadata
15
+	SetMeta(Meta)                 // Set metadata
16
+	CopyStoreObject() StoreObject // Return a copy of this object
17
+	EventCreate() Event           // Return a creation event
18
+	EventUpdate() Event           // Return an update event
19
+	EventDelete() Event           // Return a deletion event
20
+}
21
+
22
+// Event is the type used for events passed over watcher channels, and also
23
+// the type used to specify filtering in calls to Watch.
24
+type Event interface {
25
+	// TODO(stevvooe): Consider whether it makes sense to squish both the
26
+	// matcher type and the primary type into the same type. It might be better
27
+	// to build a matcher from an event prototype.
28
+
29
+	// Matches checks if this item in a watch queue Matches the event
30
+	// description.
31
+	Matches(events.Event) bool
32
+}
33
+
34
+func customIndexer(kind string, annotations *Annotations) (bool, [][]byte, error) {
35
+	var converted [][]byte
36
+
37
+	for _, entry := range annotations.Indices {
38
+		index := make([]byte, 0, len(kind)+1+len(entry.Key)+1+len(entry.Val)+1)
39
+		if kind != "" {
40
+			index = append(index, []byte(kind)...)
41
+			index = append(index, '|')
42
+		}
43
+		index = append(index, []byte(entry.Key)...)
44
+		index = append(index, '|')
45
+		index = append(index, []byte(entry.Val)...)
46
+		index = append(index, '\x00')
47
+		converted = append(converted, index)
48
+	}
49
+
50
+	// Add the null character as a terminator
51
+	return len(converted) != 0, converted, nil
52
+}
53
+
54
+func fromArgs(args ...interface{}) ([]byte, error) {
55
+	if len(args) != 1 {
56
+		return nil, fmt.Errorf("must provide only a single argument")
57
+	}
58
+	arg, ok := args[0].(string)
59
+	if !ok {
60
+		return nil, fmt.Errorf("argument must be a string: %#v", args[0])
61
+	}
62
+	// Add the null character as a terminator
63
+	arg += "\x00"
64
+	return []byte(arg), nil
65
+}
66
+
67
+func prefixFromArgs(args ...interface{}) ([]byte, error) {
68
+	val, err := fromArgs(args...)
69
+	if err != nil {
70
+		return nil, err
71
+	}
72
+
73
+	// Strip the null terminator, the rest is a prefix
74
+	n := len(val)
75
+	if n > 0 {
76
+		return val[:n-1], nil
77
+	}
78
+	return val, nil
79
+}
... ...
@@ -20,6 +20,7 @@
20 20
 
21 21
 	It has these top-level messages:
22 22
 		Version
23
+		IndexEntry
23 24
 		Annotations
24 25
 		Resources
25 26
 		ResourceRequirements
... ...
@@ -65,11 +66,13 @@
65 65
 		BlacklistedCertificate
66 66
 		HealthConfig
67 67
 		MaybeEncryptedRecord
68
+		RootRotation
68 69
 		NodeSpec
69 70
 		ServiceSpec
70 71
 		ReplicatedService
71 72
 		GlobalService
72 73
 		TaskSpec
74
+		GenericRuntimeSpec
73 75
 		NetworkAttachmentSpec
74 76
 		ContainerSpec
75 77
 		EndpointSpec
... ...
@@ -85,6 +88,8 @@
85 85
 		Network
86 86
 		Cluster
87 87
 		Secret
88
+		Resource
89
+		Extension
88 90
 		GetNodeRequest
89 91
 		GetNodeResponse
90 92
 		ListNodesRequest
... ...
@@ -324,7 +329,7 @@ func (x RaftMemberStatus_Reachability) String() string {
324 324
 	return proto.EnumName(RaftMemberStatus_Reachability_name, int32(x))
325 325
 }
326 326
 func (RaftMemberStatus_Reachability) EnumDescriptor() ([]byte, []int) {
327
-	return fileDescriptorTypes, []int{8, 0}
327
+	return fileDescriptorTypes, []int{9, 0}
328 328
 }
329 329
 
330 330
 // TODO(aluzzardi) These should be using `gogoproto.enumvalue_customname`.
... ...
@@ -357,7 +362,7 @@ var NodeStatus_State_value = map[string]int32{
357 357
 func (x NodeStatus_State) String() string {
358 358
 	return proto.EnumName(NodeStatus_State_name, int32(x))
359 359
 }
360
-func (NodeStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9, 0} }
360
+func (NodeStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10, 0} }
361 361
 
362 362
 type Mount_MountType int32
363 363
 
... ...
@@ -381,7 +386,7 @@ var Mount_MountType_value = map[string]int32{
381 381
 func (x Mount_MountType) String() string {
382 382
 	return proto.EnumName(Mount_MountType_name, int32(x))
383 383
 }
384
-func (Mount_MountType) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11, 0} }
384
+func (Mount_MountType) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12, 0} }
385 385
 
386 386
 type Mount_BindOptions_MountPropagation int32
387 387
 
... ...
@@ -415,7 +420,7 @@ func (x Mount_BindOptions_MountPropagation) String() string {
415 415
 	return proto.EnumName(Mount_BindOptions_MountPropagation_name, int32(x))
416 416
 }
417 417
 func (Mount_BindOptions_MountPropagation) EnumDescriptor() ([]byte, []int) {
418
-	return fileDescriptorTypes, []int{11, 0, 0}
418
+	return fileDescriptorTypes, []int{12, 0, 0}
419 419
 }
420 420
 
421 421
 type RestartPolicy_RestartCondition int32
... ...
@@ -441,7 +446,7 @@ func (x RestartPolicy_RestartCondition) String() string {
441 441
 	return proto.EnumName(RestartPolicy_RestartCondition_name, int32(x))
442 442
 }
443 443
 func (RestartPolicy_RestartCondition) EnumDescriptor() ([]byte, []int) {
444
-	return fileDescriptorTypes, []int{12, 0}
444
+	return fileDescriptorTypes, []int{13, 0}
445 445
 }
446 446
 
447 447
 type UpdateConfig_FailureAction int32
... ...
@@ -467,7 +472,34 @@ func (x UpdateConfig_FailureAction) String() string {
467 467
 	return proto.EnumName(UpdateConfig_FailureAction_name, int32(x))
468 468
 }
469 469
 func (UpdateConfig_FailureAction) EnumDescriptor() ([]byte, []int) {
470
-	return fileDescriptorTypes, []int{13, 0}
470
+	return fileDescriptorTypes, []int{14, 0}
471
+}
472
+
473
+// UpdateOrder controls the order of operations when rolling out an
474
+// updated task. Either the old task is shut down before the new task
475
+// is started, or the new task is started before the old task is shut
476
+// down.
477
+type UpdateConfig_UpdateOrder int32
478
+
479
+const (
480
+	UpdateConfig_STOP_FIRST  UpdateConfig_UpdateOrder = 0
481
+	UpdateConfig_START_FIRST UpdateConfig_UpdateOrder = 1
482
+)
483
+
484
+var UpdateConfig_UpdateOrder_name = map[int32]string{
485
+	0: "STOP_FIRST",
486
+	1: "START_FIRST",
487
+}
488
+var UpdateConfig_UpdateOrder_value = map[string]int32{
489
+	"STOP_FIRST":  0,
490
+	"START_FIRST": 1,
491
+}
492
+
493
+func (x UpdateConfig_UpdateOrder) String() string {
494
+	return proto.EnumName(UpdateConfig_UpdateOrder_name, int32(x))
495
+}
496
+func (UpdateConfig_UpdateOrder) EnumDescriptor() ([]byte, []int) {
497
+	return fileDescriptorTypes, []int{14, 1}
471 498
 }
472 499
 
473 500
 type UpdateStatus_UpdateState int32
... ...
@@ -505,7 +537,7 @@ func (x UpdateStatus_UpdateState) String() string {
505 505
 	return proto.EnumName(UpdateStatus_UpdateState_name, int32(x))
506 506
 }
507 507
 func (UpdateStatus_UpdateState) EnumDescriptor() ([]byte, []int) {
508
-	return fileDescriptorTypes, []int{14, 0}
508
+	return fileDescriptorTypes, []int{15, 0}
509 509
 }
510 510
 
511 511
 // AddressFamily specifies the network address family that
... ...
@@ -533,7 +565,7 @@ func (x IPAMConfig_AddressFamily) String() string {
533 533
 	return proto.EnumName(IPAMConfig_AddressFamily_name, int32(x))
534 534
 }
535 535
 func (IPAMConfig_AddressFamily) EnumDescriptor() ([]byte, []int) {
536
-	return fileDescriptorTypes, []int{19, 0}
536
+	return fileDescriptorTypes, []int{20, 0}
537 537
 }
538 538
 
539 539
 type PortConfig_Protocol int32
... ...
@@ -555,7 +587,7 @@ var PortConfig_Protocol_value = map[string]int32{
555 555
 func (x PortConfig_Protocol) String() string {
556 556
 	return proto.EnumName(PortConfig_Protocol_name, int32(x))
557 557
 }
558
-func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20, 0} }
558
+func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21, 0} }
559 559
 
560 560
 // PublishMode controls how ports are published on the swarm.
561 561
 type PortConfig_PublishMode int32
... ...
@@ -583,7 +615,7 @@ func (x PortConfig_PublishMode) String() string {
583 583
 	return proto.EnumName(PortConfig_PublishMode_name, int32(x))
584 584
 }
585 585
 func (PortConfig_PublishMode) EnumDescriptor() ([]byte, []int) {
586
-	return fileDescriptorTypes, []int{20, 1}
586
+	return fileDescriptorTypes, []int{21, 1}
587 587
 }
588 588
 
589 589
 type IssuanceStatus_State int32
... ...
@@ -623,7 +655,7 @@ var IssuanceStatus_State_value = map[string]int32{
623 623
 func (x IssuanceStatus_State) String() string {
624 624
 	return proto.EnumName(IssuanceStatus_State_name, int32(x))
625 625
 }
626
-func (IssuanceStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25, 0} }
626
+func (IssuanceStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26, 0} }
627 627
 
628 628
 type ExternalCA_CAProtocol int32
629 629
 
... ...
@@ -642,7 +674,7 @@ func (x ExternalCA_CAProtocol) String() string {
642 642
 	return proto.EnumName(ExternalCA_CAProtocol_name, int32(x))
643 643
 }
644 644
 func (ExternalCA_CAProtocol) EnumDescriptor() ([]byte, []int) {
645
-	return fileDescriptorTypes, []int{27, 0}
645
+	return fileDescriptorTypes, []int{28, 0}
646 646
 }
647 647
 
648 648
 // Encryption algorithm that can implemented using this key
... ...
@@ -663,7 +695,7 @@ func (x EncryptionKey_Algorithm) String() string {
663 663
 	return proto.EnumName(EncryptionKey_Algorithm_name, int32(x))
664 664
 }
665 665
 func (EncryptionKey_Algorithm) EnumDescriptor() ([]byte, []int) {
666
-	return fileDescriptorTypes, []int{40, 0}
666
+	return fileDescriptorTypes, []int{41, 0}
667 667
 }
668 668
 
669 669
 type MaybeEncryptedRecord_Algorithm int32
... ...
@@ -686,7 +718,7 @@ func (x MaybeEncryptedRecord_Algorithm) String() string {
686 686
 	return proto.EnumName(MaybeEncryptedRecord_Algorithm_name, int32(x))
687 687
 }
688 688
 func (MaybeEncryptedRecord_Algorithm) EnumDescriptor() ([]byte, []int) {
689
-	return fileDescriptorTypes, []int{45, 0}
689
+	return fileDescriptorTypes, []int{46, 0}
690 690
 }
691 691
 
692 692
 // Version tracks the last time an object in the store was updated.
... ...
@@ -698,16 +730,28 @@ func (m *Version) Reset()                    { *m = Version{} }
698 698
 func (*Version) ProtoMessage()               {}
699 699
 func (*Version) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{0} }
700 700
 
701
+type IndexEntry struct {
702
+	Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
703
+	Val string `protobuf:"bytes,2,opt,name=val,proto3" json:"val,omitempty"`
704
+}
705
+
706
+func (m *IndexEntry) Reset()                    { *m = IndexEntry{} }
707
+func (*IndexEntry) ProtoMessage()               {}
708
+func (*IndexEntry) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1} }
709
+
701 710
 // Annotations provide useful information to identify API objects. They are
702 711
 // common to all API specs.
703 712
 type Annotations struct {
704 713
 	Name   string            `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
705 714
 	Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
715
+	// Indices provides keys and values for indexing this object.
716
+	// A single key may have multiple values.
717
+	Indices []IndexEntry `protobuf:"bytes,4,rep,name=indices" json:"indices"`
706 718
 }
707 719
 
708 720
 func (m *Annotations) Reset()                    { *m = Annotations{} }
709 721
 func (*Annotations) ProtoMessage()               {}
710
-func (*Annotations) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1} }
722
+func (*Annotations) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{2} }
711 723
 
712 724
 type Resources struct {
713 725
 	// Amount of CPUs (e.g. 2000000000 = 2 CPU cores)
... ...
@@ -718,7 +762,7 @@ type Resources struct {
718 718
 
719 719
 func (m *Resources) Reset()                    { *m = Resources{} }
720 720
 func (*Resources) ProtoMessage()               {}
721
-func (*Resources) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{2} }
721
+func (*Resources) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{3} }
722 722
 
723 723
 type ResourceRequirements struct {
724 724
 	Limits       *Resources `protobuf:"bytes,1,opt,name=limits" json:"limits,omitempty"`
... ...
@@ -727,7 +771,7 @@ type ResourceRequirements struct {
727 727
 
728 728
 func (m *ResourceRequirements) Reset()                    { *m = ResourceRequirements{} }
729 729
 func (*ResourceRequirements) ProtoMessage()               {}
730
-func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{3} }
730
+func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{4} }
731 731
 
732 732
 type Platform struct {
733 733
 	// Architecture (e.g. x86_64)
... ...
@@ -738,7 +782,7 @@ type Platform struct {
738 738
 
739 739
 func (m *Platform) Reset()                    { *m = Platform{} }
740 740
 func (*Platform) ProtoMessage()               {}
741
-func (*Platform) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{4} }
741
+func (*Platform) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} }
742 742
 
743 743
 // PluginDescription describes an engine plugin.
744 744
 type PluginDescription struct {
... ...
@@ -752,7 +796,7 @@ type PluginDescription struct {
752 752
 
753 753
 func (m *PluginDescription) Reset()                    { *m = PluginDescription{} }
754 754
 func (*PluginDescription) ProtoMessage()               {}
755
-func (*PluginDescription) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} }
755
+func (*PluginDescription) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} }
756 756
 
757 757
 type EngineDescription struct {
758 758
 	// Docker daemon version running on the node.
... ...
@@ -765,7 +809,7 @@ type EngineDescription struct {
765 765
 
766 766
 func (m *EngineDescription) Reset()                    { *m = EngineDescription{} }
767 767
 func (*EngineDescription) ProtoMessage()               {}
768
-func (*EngineDescription) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} }
768
+func (*EngineDescription) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{7} }
769 769
 
770 770
 type NodeDescription struct {
771 771
 	// Hostname of the node as reported by the agent.
... ...
@@ -781,7 +825,7 @@ type NodeDescription struct {
781 781
 
782 782
 func (m *NodeDescription) Reset()                    { *m = NodeDescription{} }
783 783
 func (*NodeDescription) ProtoMessage()               {}
784
-func (*NodeDescription) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{7} }
784
+func (*NodeDescription) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{8} }
785 785
 
786 786
 type RaftMemberStatus struct {
787 787
 	Leader       bool                          `protobuf:"varint,1,opt,name=leader,proto3" json:"leader,omitempty"`
... ...
@@ -791,7 +835,7 @@ type RaftMemberStatus struct {
791 791
 
792 792
 func (m *RaftMemberStatus) Reset()                    { *m = RaftMemberStatus{} }
793 793
 func (*RaftMemberStatus) ProtoMessage()               {}
794
-func (*RaftMemberStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{8} }
794
+func (*RaftMemberStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9} }
795 795
 
796 796
 type NodeStatus struct {
797 797
 	State   NodeStatus_State `protobuf:"varint,1,opt,name=state,proto3,enum=docker.swarmkit.v1.NodeStatus_State" json:"state,omitempty"`
... ...
@@ -802,7 +846,7 @@ type NodeStatus struct {
802 802
 
803 803
 func (m *NodeStatus) Reset()                    { *m = NodeStatus{} }
804 804
 func (*NodeStatus) ProtoMessage()               {}
805
-func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9} }
805
+func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10} }
806 806
 
807 807
 type Image struct {
808 808
 	// reference is a docker image reference. This can include a rpository, tag
... ...
@@ -813,7 +857,7 @@ type Image struct {
813 813
 
814 814
 func (m *Image) Reset()                    { *m = Image{} }
815 815
 func (*Image) ProtoMessage()               {}
816
-func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10} }
816
+func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} }
817 817
 
818 818
 // Mount describes volume mounts for a container.
819 819
 //
... ...
@@ -848,7 +892,7 @@ type Mount struct {
848 848
 
849 849
 func (m *Mount) Reset()                    { *m = Mount{} }
850 850
 func (*Mount) ProtoMessage()               {}
851
-func (*Mount) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} }
851
+func (*Mount) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12} }
852 852
 
853 853
 // BindOptions specifies options that are specific to a bind mount.
854 854
 type Mount_BindOptions struct {
... ...
@@ -858,7 +902,7 @@ type Mount_BindOptions struct {
858 858
 
859 859
 func (m *Mount_BindOptions) Reset()                    { *m = Mount_BindOptions{} }
860 860
 func (*Mount_BindOptions) ProtoMessage()               {}
861
-func (*Mount_BindOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11, 0} }
861
+func (*Mount_BindOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12, 0} }
862 862
 
863 863
 // VolumeOptions contains parameters for mounting the volume.
864 864
 type Mount_VolumeOptions struct {
... ...
@@ -875,7 +919,7 @@ type Mount_VolumeOptions struct {
875 875
 
876 876
 func (m *Mount_VolumeOptions) Reset()                    { *m = Mount_VolumeOptions{} }
877 877
 func (*Mount_VolumeOptions) ProtoMessage()               {}
878
-func (*Mount_VolumeOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11, 1} }
878
+func (*Mount_VolumeOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12, 1} }
879 879
 
880 880
 type Mount_TmpfsOptions struct {
881 881
 	// Size sets the size of the tmpfs, in bytes.
... ...
@@ -893,7 +937,7 @@ type Mount_TmpfsOptions struct {
893 893
 
894 894
 func (m *Mount_TmpfsOptions) Reset()                    { *m = Mount_TmpfsOptions{} }
895 895
 func (*Mount_TmpfsOptions) ProtoMessage()               {}
896
-func (*Mount_TmpfsOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11, 2} }
896
+func (*Mount_TmpfsOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12, 2} }
897 897
 
898 898
 type RestartPolicy struct {
899 899
 	Condition RestartPolicy_RestartCondition `protobuf:"varint,1,opt,name=condition,proto3,enum=docker.swarmkit.v1.RestartPolicy_RestartCondition" json:"condition,omitempty"`
... ...
@@ -911,7 +955,7 @@ type RestartPolicy struct {
911 911
 
912 912
 func (m *RestartPolicy) Reset()                    { *m = RestartPolicy{} }
913 913
 func (*RestartPolicy) ProtoMessage()               {}
914
-func (*RestartPolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12} }
914
+func (*RestartPolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{13} }
915 915
 
916 916
 // UpdateConfig specifies the rate and policy of updates.
917 917
 // TODO(aluzzardi): Consider making this a oneof with RollingStrategy and LockstepStrategy.
... ...
@@ -945,12 +989,13 @@ type UpdateConfig struct {
945 945
 	// If the failure action is ROLLBACK, the orchestrator will attempt to
946 946
 	// roll back to the previous service spec. If the MaxFailureRatio
947 947
 	// threshold is hit during the rollback, the rollback will pause.
948
-	MaxFailureRatio float32 `protobuf:"fixed32,5,opt,name=max_failure_ratio,json=maxFailureRatio,proto3" json:"max_failure_ratio,omitempty"`
948
+	MaxFailureRatio float32                  `protobuf:"fixed32,5,opt,name=max_failure_ratio,json=maxFailureRatio,proto3" json:"max_failure_ratio,omitempty"`
949
+	Order           UpdateConfig_UpdateOrder `protobuf:"varint,6,opt,name=order,proto3,enum=docker.swarmkit.v1.UpdateConfig_UpdateOrder" json:"order,omitempty"`
949 950
 }
950 951
 
951 952
 func (m *UpdateConfig) Reset()                    { *m = UpdateConfig{} }
952 953
 func (*UpdateConfig) ProtoMessage()               {}
953
-func (*UpdateConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{13} }
954
+func (*UpdateConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{14} }
954 955
 
955 956
 // UpdateStatus is the status of an update in progress.
956 957
 type UpdateStatus struct {
... ...
@@ -974,7 +1019,7 @@ type UpdateStatus struct {
974 974
 
975 975
 func (m *UpdateStatus) Reset()                    { *m = UpdateStatus{} }
976 976
 func (*UpdateStatus) ProtoMessage()               {}
977
-func (*UpdateStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{14} }
977
+func (*UpdateStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{15} }
978 978
 
979 979
 // Container specific status.
980 980
 type ContainerStatus struct {
... ...
@@ -985,7 +1030,7 @@ type ContainerStatus struct {
985 985
 
986 986
 func (m *ContainerStatus) Reset()                    { *m = ContainerStatus{} }
987 987
 func (*ContainerStatus) ProtoMessage()               {}
988
-func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{15} }
988
+func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{16} }
989 989
 
990 990
 // PortStatus specifies the actual allocated runtime state of a list
991 991
 // of port configs.
... ...
@@ -995,7 +1040,7 @@ type PortStatus struct {
995 995
 
996 996
 func (m *PortStatus) Reset()                    { *m = PortStatus{} }
997 997
 func (*PortStatus) ProtoMessage()               {}
998
-func (*PortStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{16} }
998
+func (*PortStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} }
999 999
 
1000 1000
 type TaskStatus struct {
1001 1001
 	// Note: can't use stdtime because this field is nullable.
... ...
@@ -1032,7 +1077,7 @@ type TaskStatus struct {
1032 1032
 
1033 1033
 func (m *TaskStatus) Reset()                    { *m = TaskStatus{} }
1034 1034
 func (*TaskStatus) ProtoMessage()               {}
1035
-func (*TaskStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} }
1035
+func (*TaskStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} }
1036 1036
 
1037 1037
 type isTaskStatus_RuntimeStatus interface {
1038 1038
 	isTaskStatus_RuntimeStatus()
... ...
@@ -1134,7 +1179,7 @@ type NetworkAttachmentConfig struct {
1134 1134
 
1135 1135
 func (m *NetworkAttachmentConfig) Reset()                    { *m = NetworkAttachmentConfig{} }
1136 1136
 func (*NetworkAttachmentConfig) ProtoMessage()               {}
1137
-func (*NetworkAttachmentConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} }
1137
+func (*NetworkAttachmentConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} }
1138 1138
 
1139 1139
 // IPAMConfig specifies parameters for IP Address Management.
1140 1140
 type IPAMConfig struct {
... ...
@@ -1155,7 +1200,7 @@ type IPAMConfig struct {
1155 1155
 
1156 1156
 func (m *IPAMConfig) Reset()                    { *m = IPAMConfig{} }
1157 1157
 func (*IPAMConfig) ProtoMessage()               {}
1158
-func (*IPAMConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} }
1158
+func (*IPAMConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
1159 1159
 
1160 1160
 // PortConfig specifies an exposed port which can be
1161 1161
 // addressed using the given name. This can be later queried
... ...
@@ -1181,7 +1226,7 @@ type PortConfig struct {
1181 1181
 
1182 1182
 func (m *PortConfig) Reset()                    { *m = PortConfig{} }
1183 1183
 func (*PortConfig) ProtoMessage()               {}
1184
-func (*PortConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
1184
+func (*PortConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} }
1185 1185
 
1186 1186
 // Driver is a generic driver type to be used throughout the API. For now, a
1187 1187
 // driver is simply a name and set of options. The field contents depend on the
... ...
@@ -1194,7 +1239,7 @@ type Driver struct {
1194 1194
 
1195 1195
 func (m *Driver) Reset()                    { *m = Driver{} }
1196 1196
 func (*Driver) ProtoMessage()               {}
1197
-func (*Driver) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} }
1197
+func (*Driver) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} }
1198 1198
 
1199 1199
 type IPAMOptions struct {
1200 1200
 	Driver  *Driver       `protobuf:"bytes,1,opt,name=driver" json:"driver,omitempty"`
... ...
@@ -1203,7 +1248,7 @@ type IPAMOptions struct {
1203 1203
 
1204 1204
 func (m *IPAMOptions) Reset()                    { *m = IPAMOptions{} }
1205 1205
 func (*IPAMOptions) ProtoMessage()               {}
1206
-func (*IPAMOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} }
1206
+func (*IPAMOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} }
1207 1207
 
1208 1208
 // Peer should be used anywhere where we are describing a remote peer.
1209 1209
 type Peer struct {
... ...
@@ -1213,7 +1258,7 @@ type Peer struct {
1213 1213
 
1214 1214
 func (m *Peer) Reset()                    { *m = Peer{} }
1215 1215
 func (*Peer) ProtoMessage()               {}
1216
-func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} }
1216
+func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} }
1217 1217
 
1218 1218
 // WeightedPeer should be used anywhere where we are describing a remote peer
1219 1219
 // with a weight.
... ...
@@ -1224,7 +1269,7 @@ type WeightedPeer struct {
1224 1224
 
1225 1225
 func (m *WeightedPeer) Reset()                    { *m = WeightedPeer{} }
1226 1226
 func (*WeightedPeer) ProtoMessage()               {}
1227
-func (*WeightedPeer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} }
1227
+func (*WeightedPeer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} }
1228 1228
 
1229 1229
 type IssuanceStatus struct {
1230 1230
 	State IssuanceStatus_State `protobuf:"varint,1,opt,name=state,proto3,enum=docker.swarmkit.v1.IssuanceStatus_State" json:"state,omitempty"`
... ...
@@ -1236,7 +1281,7 @@ type IssuanceStatus struct {
1236 1236
 
1237 1237
 func (m *IssuanceStatus) Reset()                    { *m = IssuanceStatus{} }
1238 1238
 func (*IssuanceStatus) ProtoMessage()               {}
1239
-func (*IssuanceStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} }
1239
+func (*IssuanceStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
1240 1240
 
1241 1241
 type AcceptancePolicy struct {
1242 1242
 	Policies []*AcceptancePolicy_RoleAdmissionPolicy `protobuf:"bytes,1,rep,name=policies" json:"policies,omitempty"`
... ...
@@ -1244,7 +1289,7 @@ type AcceptancePolicy struct {
1244 1244
 
1245 1245
 func (m *AcceptancePolicy) Reset()                    { *m = AcceptancePolicy{} }
1246 1246
 func (*AcceptancePolicy) ProtoMessage()               {}
1247
-func (*AcceptancePolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
1247
+func (*AcceptancePolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
1248 1248
 
1249 1249
 type AcceptancePolicy_RoleAdmissionPolicy struct {
1250 1250
 	Role NodeRole `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
... ...
@@ -1259,7 +1304,7 @@ type AcceptancePolicy_RoleAdmissionPolicy struct {
1259 1259
 func (m *AcceptancePolicy_RoleAdmissionPolicy) Reset()      { *m = AcceptancePolicy_RoleAdmissionPolicy{} }
1260 1260
 func (*AcceptancePolicy_RoleAdmissionPolicy) ProtoMessage() {}
1261 1261
 func (*AcceptancePolicy_RoleAdmissionPolicy) Descriptor() ([]byte, []int) {
1262
-	return fileDescriptorTypes, []int{26, 0}
1262
+	return fileDescriptorTypes, []int{27, 0}
1263 1263
 }
1264 1264
 
1265 1265
 type AcceptancePolicy_RoleAdmissionPolicy_Secret struct {
... ...
@@ -1274,7 +1319,7 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Reset() {
1274 1274
 }
1275 1275
 func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) ProtoMessage() {}
1276 1276
 func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) Descriptor() ([]byte, []int) {
1277
-	return fileDescriptorTypes, []int{26, 0, 0}
1277
+	return fileDescriptorTypes, []int{27, 0, 0}
1278 1278
 }
1279 1279
 
1280 1280
 type ExternalCA struct {
... ...
@@ -1285,11 +1330,13 @@ type ExternalCA struct {
1285 1285
 	// Options is a set of additional key/value pairs whose interpretation
1286 1286
 	// depends on the specified CA type.
1287 1287
 	Options map[string]string `protobuf:"bytes,3,rep,name=options" json:"options,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
1288
+	// CACert specifies which root CA is used by this external CA
1289
+	CACert []byte `protobuf:"bytes,4,opt,name=ca_cert,json=caCert,proto3" json:"ca_cert,omitempty"`
1288 1290
 }
1289 1291
 
1290 1292
 func (m *ExternalCA) Reset()                    { *m = ExternalCA{} }
1291 1293
 func (*ExternalCA) ProtoMessage()               {}
1292
-func (*ExternalCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
1294
+func (*ExternalCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
1293 1295
 
1294 1296
 type CAConfig struct {
1295 1297
 	// NodeCertExpiry is the duration certificates should be issued for
... ...
@@ -1302,7 +1349,7 @@ type CAConfig struct {
1302 1302
 
1303 1303
 func (m *CAConfig) Reset()                    { *m = CAConfig{} }
1304 1304
 func (*CAConfig) ProtoMessage()               {}
1305
-func (*CAConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
1305
+func (*CAConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
1306 1306
 
1307 1307
 // OrchestrationConfig defines cluster-level orchestration settings.
1308 1308
 type OrchestrationConfig struct {
... ...
@@ -1313,7 +1360,7 @@ type OrchestrationConfig struct {
1313 1313
 
1314 1314
 func (m *OrchestrationConfig) Reset()                    { *m = OrchestrationConfig{} }
1315 1315
 func (*OrchestrationConfig) ProtoMessage()               {}
1316
-func (*OrchestrationConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
1316
+func (*OrchestrationConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
1317 1317
 
1318 1318
 // TaskDefaults specifies default values for task creation.
1319 1319
 type TaskDefaults struct {
... ...
@@ -1327,7 +1374,7 @@ type TaskDefaults struct {
1327 1327
 
1328 1328
 func (m *TaskDefaults) Reset()                    { *m = TaskDefaults{} }
1329 1329
 func (*TaskDefaults) ProtoMessage()               {}
1330
-func (*TaskDefaults) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
1330
+func (*TaskDefaults) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
1331 1331
 
1332 1332
 // DispatcherConfig defines cluster-level dispatcher settings.
1333 1333
 type DispatcherConfig struct {
... ...
@@ -1339,7 +1386,7 @@ type DispatcherConfig struct {
1339 1339
 
1340 1340
 func (m *DispatcherConfig) Reset()                    { *m = DispatcherConfig{} }
1341 1341
 func (*DispatcherConfig) ProtoMessage()               {}
1342
-func (*DispatcherConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
1342
+func (*DispatcherConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
1343 1343
 
1344 1344
 // RaftConfig defines raft settings for the cluster.
1345 1345
 type RaftConfig struct {
... ...
@@ -1361,7 +1408,7 @@ type RaftConfig struct {
1361 1361
 
1362 1362
 func (m *RaftConfig) Reset()                    { *m = RaftConfig{} }
1363 1363
 func (*RaftConfig) ProtoMessage()               {}
1364
-func (*RaftConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
1364
+func (*RaftConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
1365 1365
 
1366 1366
 type EncryptionConfig struct {
1367 1367
 	// AutoLockManagers specifies whether or not managers TLS keys and raft data
... ...
@@ -1372,7 +1419,7 @@ type EncryptionConfig struct {
1372 1372
 
1373 1373
 func (m *EncryptionConfig) Reset()                    { *m = EncryptionConfig{} }
1374 1374
 func (*EncryptionConfig) ProtoMessage()               {}
1375
-func (*EncryptionConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
1375
+func (*EncryptionConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} }
1376 1376
 
1377 1377
 type SpreadOver struct {
1378 1378
 	SpreadDescriptor string `protobuf:"bytes,1,opt,name=spread_descriptor,json=spreadDescriptor,proto3" json:"spread_descriptor,omitempty"`
... ...
@@ -1380,7 +1427,7 @@ type SpreadOver struct {
1380 1380
 
1381 1381
 func (m *SpreadOver) Reset()                    { *m = SpreadOver{} }
1382 1382
 func (*SpreadOver) ProtoMessage()               {}
1383
-func (*SpreadOver) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} }
1383
+func (*SpreadOver) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} }
1384 1384
 
1385 1385
 type PlacementPreference struct {
1386 1386
 	// Types that are valid to be assigned to Preference:
... ...
@@ -1390,7 +1437,7 @@ type PlacementPreference struct {
1390 1390
 
1391 1391
 func (m *PlacementPreference) Reset()                    { *m = PlacementPreference{} }
1392 1392
 func (*PlacementPreference) ProtoMessage()               {}
1393
-func (*PlacementPreference) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} }
1393
+func (*PlacementPreference) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{36} }
1394 1394
 
1395 1395
 type isPlacementPreference_Preference interface {
1396 1396
 	isPlacementPreference_Preference()
... ...
@@ -1485,7 +1532,7 @@ type Placement struct {
1485 1485
 
1486 1486
 func (m *Placement) Reset()                    { *m = Placement{} }
1487 1487
 func (*Placement) ProtoMessage()               {}
1488
-func (*Placement) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{36} }
1488
+func (*Placement) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{37} }
1489 1489
 
1490 1490
 // JoinToken contains the join tokens for workers and managers.
1491 1491
 type JoinTokens struct {
... ...
@@ -1497,7 +1544,7 @@ type JoinTokens struct {
1497 1497
 
1498 1498
 func (m *JoinTokens) Reset()                    { *m = JoinTokens{} }
1499 1499
 func (*JoinTokens) ProtoMessage()               {}
1500
-func (*JoinTokens) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{37} }
1500
+func (*JoinTokens) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{38} }
1501 1501
 
1502 1502
 type RootCA struct {
1503 1503
 	// CAKey is the root CA private key.
... ...
@@ -1508,11 +1555,14 @@ type RootCA struct {
1508 1508
 	CACertHash string `protobuf:"bytes,3,opt,name=ca_cert_hash,json=caCertHash,proto3" json:"ca_cert_hash,omitempty"`
1509 1509
 	// JoinTokens contains the join tokens for workers and managers.
1510 1510
 	JoinTokens JoinTokens `protobuf:"bytes,4,opt,name=join_tokens,json=joinTokens" json:"join_tokens"`
1511
+	// RootRotation contains the new root cert and key we want to rotate to - if this is nil, we are not in the
1512
+	// middle of a root rotation
1513
+	RootRotation *RootRotation `protobuf:"bytes,5,opt,name=root_rotation,json=rootRotation" json:"root_rotation,omitempty"`
1511 1514
 }
1512 1515
 
1513 1516
 func (m *RootCA) Reset()                    { *m = RootCA{} }
1514 1517
 func (*RootCA) ProtoMessage()               {}
1515
-func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{38} }
1518
+func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{39} }
1516 1519
 
1517 1520
 type Certificate struct {
1518 1521
 	Role        NodeRole       `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
... ...
@@ -1525,7 +1575,7 @@ type Certificate struct {
1525 1525
 
1526 1526
 func (m *Certificate) Reset()                    { *m = Certificate{} }
1527 1527
 func (*Certificate) ProtoMessage()               {}
1528
-func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{39} }
1528
+func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{40} }
1529 1529
 
1530 1530
 // Symmetric keys to encrypt inter-agent communication.
1531 1531
 type EncryptionKey struct {
... ...
@@ -1541,7 +1591,7 @@ type EncryptionKey struct {
1541 1541
 
1542 1542
 func (m *EncryptionKey) Reset()                    { *m = EncryptionKey{} }
1543 1543
 func (*EncryptionKey) ProtoMessage()               {}
1544
-func (*EncryptionKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{40} }
1544
+func (*EncryptionKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{41} }
1545 1545
 
1546 1546
 // ManagerStatus provides informations about the state of a manager in the cluster.
1547 1547
 type ManagerStatus struct {
... ...
@@ -1558,7 +1608,7 @@ type ManagerStatus struct {
1558 1558
 
1559 1559
 func (m *ManagerStatus) Reset()                    { *m = ManagerStatus{} }
1560 1560
 func (*ManagerStatus) ProtoMessage()               {}
1561
-func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{41} }
1561
+func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{42} }
1562 1562
 
1563 1563
 // SecretReference is the linkage between a service and a secret that it uses.
1564 1564
 type SecretReference struct {
... ...
@@ -1578,7 +1628,7 @@ type SecretReference struct {
1578 1578
 
1579 1579
 func (m *SecretReference) Reset()                    { *m = SecretReference{} }
1580 1580
 func (*SecretReference) ProtoMessage()               {}
1581
-func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{42} }
1581
+func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{43} }
1582 1582
 
1583 1583
 type isSecretReference_Target interface {
1584 1584
 	isSecretReference_Target()
... ...
@@ -1676,7 +1726,7 @@ type SecretReference_FileTarget struct {
1676 1676
 func (m *SecretReference_FileTarget) Reset()      { *m = SecretReference_FileTarget{} }
1677 1677
 func (*SecretReference_FileTarget) ProtoMessage() {}
1678 1678
 func (*SecretReference_FileTarget) Descriptor() ([]byte, []int) {
1679
-	return fileDescriptorTypes, []int{42, 0}
1679
+	return fileDescriptorTypes, []int{43, 0}
1680 1680
 }
1681 1681
 
1682 1682
 // BlacklistedCertificate is a record for a blacklisted certificate. It does not
... ...
@@ -1690,7 +1740,7 @@ type BlacklistedCertificate struct {
1690 1690
 
1691 1691
 func (m *BlacklistedCertificate) Reset()                    { *m = BlacklistedCertificate{} }
1692 1692
 func (*BlacklistedCertificate) ProtoMessage()               {}
1693
-func (*BlacklistedCertificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{43} }
1693
+func (*BlacklistedCertificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{44} }
1694 1694
 
1695 1695
 // HealthConfig holds configuration settings for the HEALTHCHECK feature.
1696 1696
 type HealthConfig struct {
... ...
@@ -1712,11 +1762,15 @@ type HealthConfig struct {
1712 1712
 	// Retries is the number of consecutive failures needed to consider a
1713 1713
 	// container as unhealthy. Zero means inherit.
1714 1714
 	Retries int32 `protobuf:"varint,4,opt,name=retries,proto3" json:"retries,omitempty"`
1715
+	// Start period is the period for container initialization during
1716
+	// which health check failures will note count towards the maximum
1717
+	// number of retries.
1718
+	StartPeriod *google_protobuf1.Duration `protobuf:"bytes,5,opt,name=start_period,json=startPeriod" json:"start_period,omitempty"`
1715 1719
 }
1716 1720
 
1717 1721
 func (m *HealthConfig) Reset()                    { *m = HealthConfig{} }
1718 1722
 func (*HealthConfig) ProtoMessage()               {}
1719
-func (*HealthConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{44} }
1723
+func (*HealthConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{45} }
1720 1724
 
1721 1725
 type MaybeEncryptedRecord struct {
1722 1726
 	Algorithm MaybeEncryptedRecord_Algorithm `protobuf:"varint,1,opt,name=algorithm,proto3,enum=docker.swarmkit.v1.MaybeEncryptedRecord_Algorithm" json:"algorithm,omitempty"`
... ...
@@ -1726,10 +1780,22 @@ type MaybeEncryptedRecord struct {
1726 1726
 
1727 1727
 func (m *MaybeEncryptedRecord) Reset()                    { *m = MaybeEncryptedRecord{} }
1728 1728
 func (*MaybeEncryptedRecord) ProtoMessage()               {}
1729
-func (*MaybeEncryptedRecord) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{45} }
1729
+func (*MaybeEncryptedRecord) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{46} }
1730
+
1731
+type RootRotation struct {
1732
+	CACert []byte `protobuf:"bytes,1,opt,name=ca_cert,json=caCert,proto3" json:"ca_cert,omitempty"`
1733
+	CAKey  []byte `protobuf:"bytes,2,opt,name=ca_key,json=caKey,proto3" json:"ca_key,omitempty"`
1734
+	// cross-signed CA cert is the CACert that has been cross-signed by the previous root
1735
+	CrossSignedCACert []byte `protobuf:"bytes,3,opt,name=cross_signed_ca_cert,json=crossSignedCaCert,proto3" json:"cross_signed_ca_cert,omitempty"`
1736
+}
1737
+
1738
+func (m *RootRotation) Reset()                    { *m = RootRotation{} }
1739
+func (*RootRotation) ProtoMessage()               {}
1740
+func (*RootRotation) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{47} }
1730 1741
 
1731 1742
 func init() {
1732 1743
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
1744
+	proto.RegisterType((*IndexEntry)(nil), "docker.swarmkit.v1.IndexEntry")
1733 1745
 	proto.RegisterType((*Annotations)(nil), "docker.swarmkit.v1.Annotations")
1734 1746
 	proto.RegisterType((*Resources)(nil), "docker.swarmkit.v1.Resources")
1735 1747
 	proto.RegisterType((*ResourceRequirements)(nil), "docker.swarmkit.v1.ResourceRequirements")
... ...
@@ -1781,6 +1847,7 @@ func init() {
1781 1781
 	proto.RegisterType((*BlacklistedCertificate)(nil), "docker.swarmkit.v1.BlacklistedCertificate")
1782 1782
 	proto.RegisterType((*HealthConfig)(nil), "docker.swarmkit.v1.HealthConfig")
1783 1783
 	proto.RegisterType((*MaybeEncryptedRecord)(nil), "docker.swarmkit.v1.MaybeEncryptedRecord")
1784
+	proto.RegisterType((*RootRotation)(nil), "docker.swarmkit.v1.RootRotation")
1784 1785
 	proto.RegisterEnum("docker.swarmkit.v1.TaskState", TaskState_name, TaskState_value)
1785 1786
 	proto.RegisterEnum("docker.swarmkit.v1.NodeRole", NodeRole_name, NodeRole_value)
1786 1787
 	proto.RegisterEnum("docker.swarmkit.v1.RaftMemberStatus_Reachability", RaftMemberStatus_Reachability_name, RaftMemberStatus_Reachability_value)
... ...
@@ -1789,6 +1856,7 @@ func init() {
1789 1789
 	proto.RegisterEnum("docker.swarmkit.v1.Mount_BindOptions_MountPropagation", Mount_BindOptions_MountPropagation_name, Mount_BindOptions_MountPropagation_value)
1790 1790
 	proto.RegisterEnum("docker.swarmkit.v1.RestartPolicy_RestartCondition", RestartPolicy_RestartCondition_name, RestartPolicy_RestartCondition_value)
1791 1791
 	proto.RegisterEnum("docker.swarmkit.v1.UpdateConfig_FailureAction", UpdateConfig_FailureAction_name, UpdateConfig_FailureAction_value)
1792
+	proto.RegisterEnum("docker.swarmkit.v1.UpdateConfig_UpdateOrder", UpdateConfig_UpdateOrder_name, UpdateConfig_UpdateOrder_value)
1792 1793
 	proto.RegisterEnum("docker.swarmkit.v1.UpdateStatus_UpdateState", UpdateStatus_UpdateState_name, UpdateStatus_UpdateState_value)
1793 1794
 	proto.RegisterEnum("docker.swarmkit.v1.IPAMConfig_AddressFamily", IPAMConfig_AddressFamily_name, IPAMConfig_AddressFamily_value)
1794 1795
 	proto.RegisterEnum("docker.swarmkit.v1.PortConfig_Protocol", PortConfig_Protocol_name, PortConfig_Protocol_value)
... ...
@@ -1814,6 +1882,21 @@ func (m *Version) CopyFrom(src interface{}) {
1814 1814
 	*m = *o
1815 1815
 }
1816 1816
 
1817
+func (m *IndexEntry) Copy() *IndexEntry {
1818
+	if m == nil {
1819
+		return nil
1820
+	}
1821
+	o := &IndexEntry{}
1822
+	o.CopyFrom(m)
1823
+	return o
1824
+}
1825
+
1826
+func (m *IndexEntry) CopyFrom(src interface{}) {
1827
+
1828
+	o := src.(*IndexEntry)
1829
+	*m = *o
1830
+}
1831
+
1817 1832
 func (m *Annotations) Copy() *Annotations {
1818 1833
 	if m == nil {
1819 1834
 		return nil
... ...
@@ -1834,6 +1917,13 @@ func (m *Annotations) CopyFrom(src interface{}) {
1834 1834
 		}
1835 1835
 	}
1836 1836
 
1837
+	if o.Indices != nil {
1838
+		m.Indices = make([]IndexEntry, len(o.Indices))
1839
+		for i := range m.Indices {
1840
+			github_com_docker_swarmkit_api_deepcopy.Copy(&m.Indices[i], &o.Indices[i])
1841
+		}
1842
+	}
1843
+
1837 1844
 }
1838 1845
 
1839 1846
 func (m *Resources) Copy() *Resources {
... ...
@@ -2673,6 +2763,10 @@ func (m *RootCA) CopyFrom(src interface{}) {
2673 2673
 	o := src.(*RootCA)
2674 2674
 	*m = *o
2675 2675
 	github_com_docker_swarmkit_api_deepcopy.Copy(&m.JoinTokens, &o.JoinTokens)
2676
+	if o.RootRotation != nil {
2677
+		m.RootRotation = &RootRotation{}
2678
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.RootRotation, o.RootRotation)
2679
+	}
2676 2680
 }
2677 2681
 
2678 2682
 func (m *Certificate) Copy() *Certificate {
... ...
@@ -2807,6 +2901,10 @@ func (m *HealthConfig) CopyFrom(src interface{}) {
2807 2807
 		m.Timeout = &google_protobuf1.Duration{}
2808 2808
 		github_com_docker_swarmkit_api_deepcopy.Copy(m.Timeout, o.Timeout)
2809 2809
 	}
2810
+	if o.StartPeriod != nil {
2811
+		m.StartPeriod = &google_protobuf1.Duration{}
2812
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.StartPeriod, o.StartPeriod)
2813
+	}
2810 2814
 }
2811 2815
 
2812 2816
 func (m *MaybeEncryptedRecord) Copy() *MaybeEncryptedRecord {
... ...
@@ -2824,6 +2922,21 @@ func (m *MaybeEncryptedRecord) CopyFrom(src interface{}) {
2824 2824
 	*m = *o
2825 2825
 }
2826 2826
 
2827
+func (m *RootRotation) Copy() *RootRotation {
2828
+	if m == nil {
2829
+		return nil
2830
+	}
2831
+	o := &RootRotation{}
2832
+	o.CopyFrom(m)
2833
+	return o
2834
+}
2835
+
2836
+func (m *RootRotation) CopyFrom(src interface{}) {
2837
+
2838
+	o := src.(*RootRotation)
2839
+	*m = *o
2840
+}
2841
+
2827 2842
 func (m *Version) Marshal() (dAtA []byte, err error) {
2828 2843
 	size := m.Size()
2829 2844
 	dAtA = make([]byte, size)
... ...
@@ -2847,6 +2960,36 @@ func (m *Version) MarshalTo(dAtA []byte) (int, error) {
2847 2847
 	return i, nil
2848 2848
 }
2849 2849
 
2850
+func (m *IndexEntry) Marshal() (dAtA []byte, err error) {
2851
+	size := m.Size()
2852
+	dAtA = make([]byte, size)
2853
+	n, err := m.MarshalTo(dAtA)
2854
+	if err != nil {
2855
+		return nil, err
2856
+	}
2857
+	return dAtA[:n], nil
2858
+}
2859
+
2860
+func (m *IndexEntry) MarshalTo(dAtA []byte) (int, error) {
2861
+	var i int
2862
+	_ = i
2863
+	var l int
2864
+	_ = l
2865
+	if len(m.Key) > 0 {
2866
+		dAtA[i] = 0xa
2867
+		i++
2868
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Key)))
2869
+		i += copy(dAtA[i:], m.Key)
2870
+	}
2871
+	if len(m.Val) > 0 {
2872
+		dAtA[i] = 0x12
2873
+		i++
2874
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Val)))
2875
+		i += copy(dAtA[i:], m.Val)
2876
+	}
2877
+	return i, nil
2878
+}
2879
+
2850 2880
 func (m *Annotations) Marshal() (dAtA []byte, err error) {
2851 2881
 	size := m.Size()
2852 2882
 	dAtA = make([]byte, size)
... ...
@@ -2885,6 +3028,18 @@ func (m *Annotations) MarshalTo(dAtA []byte) (int, error) {
2885 2885
 			i += copy(dAtA[i:], v)
2886 2886
 		}
2887 2887
 	}
2888
+	if len(m.Indices) > 0 {
2889
+		for _, msg := range m.Indices {
2890
+			dAtA[i] = 0x22
2891
+			i++
2892
+			i = encodeVarintTypes(dAtA, i, uint64(msg.Size()))
2893
+			n, err := msg.MarshalTo(dAtA[i:])
2894
+			if err != nil {
2895
+				return 0, err
2896
+			}
2897
+			i += n
2898
+		}
2899
+	}
2888 2900
 	return i, nil
2889 2901
 }
2890 2902
 
... ...
@@ -3496,6 +3651,11 @@ func (m *UpdateConfig) MarshalTo(dAtA []byte) (int, error) {
3496 3496
 		i++
3497 3497
 		i = encodeFixed32Types(dAtA, i, uint32(math.Float32bits(float32(m.MaxFailureRatio))))
3498 3498
 	}
3499
+	if m.Order != 0 {
3500
+		dAtA[i] = 0x30
3501
+		i++
3502
+		i = encodeVarintTypes(dAtA, i, uint64(m.Order))
3503
+	}
3499 3504
 	return i, nil
3500 3505
 }
3501 3506
 
... ...
@@ -4163,6 +4323,12 @@ func (m *ExternalCA) MarshalTo(dAtA []byte) (int, error) {
4163 4163
 			i += copy(dAtA[i:], v)
4164 4164
 		}
4165 4165
 	}
4166
+	if len(m.CACert) > 0 {
4167
+		dAtA[i] = 0x22
4168
+		i++
4169
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.CACert)))
4170
+		i += copy(dAtA[i:], m.CACert)
4171
+	}
4166 4172
 	return i, nil
4167 4173
 }
4168 4174
 
... ...
@@ -4535,6 +4701,16 @@ func (m *RootCA) MarshalTo(dAtA []byte) (int, error) {
4535 4535
 		return 0, err
4536 4536
 	}
4537 4537
 	i += n28
4538
+	if m.RootRotation != nil {
4539
+		dAtA[i] = 0x2a
4540
+		i++
4541
+		i = encodeVarintTypes(dAtA, i, uint64(m.RootRotation.Size()))
4542
+		n29, err := m.RootRotation.MarshalTo(dAtA[i:])
4543
+		if err != nil {
4544
+			return 0, err
4545
+		}
4546
+		i += n29
4547
+	}
4538 4548
 	return i, nil
4539 4549
 }
4540 4550
 
... ...
@@ -4567,11 +4743,11 @@ func (m *Certificate) MarshalTo(dAtA []byte) (int, error) {
4567 4567
 	dAtA[i] = 0x1a
4568 4568
 	i++
4569 4569
 	i = encodeVarintTypes(dAtA, i, uint64(m.Status.Size()))
4570
-	n29, err := m.Status.MarshalTo(dAtA[i:])
4570
+	n30, err := m.Status.MarshalTo(dAtA[i:])
4571 4571
 	if err != nil {
4572 4572
 		return 0, err
4573 4573
 	}
4574
-	i += n29
4574
+	i += n30
4575 4575
 	if len(m.Certificate) > 0 {
4576 4576
 		dAtA[i] = 0x22
4577 4577
 		i++
... ...
@@ -4699,11 +4875,11 @@ func (m *SecretReference) MarshalTo(dAtA []byte) (int, error) {
4699 4699
 		i += copy(dAtA[i:], m.SecretName)
4700 4700
 	}
4701 4701
 	if m.Target != nil {
4702
-		nn30, err := m.Target.MarshalTo(dAtA[i:])
4702
+		nn31, err := m.Target.MarshalTo(dAtA[i:])
4703 4703
 		if err != nil {
4704 4704
 			return 0, err
4705 4705
 		}
4706
-		i += nn30
4706
+		i += nn31
4707 4707
 	}
4708 4708
 	return i, nil
4709 4709
 }
... ...
@@ -4714,11 +4890,11 @@ func (m *SecretReference_File) MarshalTo(dAtA []byte) (int, error) {
4714 4714
 		dAtA[i] = 0x1a
4715 4715
 		i++
4716 4716
 		i = encodeVarintTypes(dAtA, i, uint64(m.File.Size()))
4717
-		n31, err := m.File.MarshalTo(dAtA[i:])
4717
+		n32, err := m.File.MarshalTo(dAtA[i:])
4718 4718
 		if err != nil {
4719 4719
 			return 0, err
4720 4720
 		}
4721
-		i += n31
4721
+		i += n32
4722 4722
 	}
4723 4723
 	return i, nil
4724 4724
 }
... ...
@@ -4782,11 +4958,11 @@ func (m *BlacklistedCertificate) MarshalTo(dAtA []byte) (int, error) {
4782 4782
 		dAtA[i] = 0xa
4783 4783
 		i++
4784 4784
 		i = encodeVarintTypes(dAtA, i, uint64(m.Expiry.Size()))
4785
-		n32, err := m.Expiry.MarshalTo(dAtA[i:])
4785
+		n33, err := m.Expiry.MarshalTo(dAtA[i:])
4786 4786
 		if err != nil {
4787 4787
 			return 0, err
4788 4788
 		}
4789
-		i += n32
4789
+		i += n33
4790 4790
 	}
4791 4791
 	return i, nil
4792 4792
 }
... ...
@@ -4825,27 +5001,37 @@ func (m *HealthConfig) MarshalTo(dAtA []byte) (int, error) {
4825 4825
 		dAtA[i] = 0x12
4826 4826
 		i++
4827 4827
 		i = encodeVarintTypes(dAtA, i, uint64(m.Interval.Size()))
4828
-		n33, err := m.Interval.MarshalTo(dAtA[i:])
4828
+		n34, err := m.Interval.MarshalTo(dAtA[i:])
4829 4829
 		if err != nil {
4830 4830
 			return 0, err
4831 4831
 		}
4832
-		i += n33
4832
+		i += n34
4833 4833
 	}
4834 4834
 	if m.Timeout != nil {
4835 4835
 		dAtA[i] = 0x1a
4836 4836
 		i++
4837 4837
 		i = encodeVarintTypes(dAtA, i, uint64(m.Timeout.Size()))
4838
-		n34, err := m.Timeout.MarshalTo(dAtA[i:])
4838
+		n35, err := m.Timeout.MarshalTo(dAtA[i:])
4839 4839
 		if err != nil {
4840 4840
 			return 0, err
4841 4841
 		}
4842
-		i += n34
4842
+		i += n35
4843 4843
 	}
4844 4844
 	if m.Retries != 0 {
4845 4845
 		dAtA[i] = 0x20
4846 4846
 		i++
4847 4847
 		i = encodeVarintTypes(dAtA, i, uint64(m.Retries))
4848 4848
 	}
4849
+	if m.StartPeriod != nil {
4850
+		dAtA[i] = 0x2a
4851
+		i++
4852
+		i = encodeVarintTypes(dAtA, i, uint64(m.StartPeriod.Size()))
4853
+		n36, err := m.StartPeriod.MarshalTo(dAtA[i:])
4854
+		if err != nil {
4855
+			return 0, err
4856
+		}
4857
+		i += n36
4858
+	}
4849 4859
 	return i, nil
4850 4860
 }
4851 4861
 
... ...
@@ -4884,6 +5070,42 @@ func (m *MaybeEncryptedRecord) MarshalTo(dAtA []byte) (int, error) {
4884 4884
 	return i, nil
4885 4885
 }
4886 4886
 
4887
+func (m *RootRotation) Marshal() (dAtA []byte, err error) {
4888
+	size := m.Size()
4889
+	dAtA = make([]byte, size)
4890
+	n, err := m.MarshalTo(dAtA)
4891
+	if err != nil {
4892
+		return nil, err
4893
+	}
4894
+	return dAtA[:n], nil
4895
+}
4896
+
4897
+func (m *RootRotation) MarshalTo(dAtA []byte) (int, error) {
4898
+	var i int
4899
+	_ = i
4900
+	var l int
4901
+	_ = l
4902
+	if len(m.CACert) > 0 {
4903
+		dAtA[i] = 0xa
4904
+		i++
4905
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.CACert)))
4906
+		i += copy(dAtA[i:], m.CACert)
4907
+	}
4908
+	if len(m.CAKey) > 0 {
4909
+		dAtA[i] = 0x12
4910
+		i++
4911
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.CAKey)))
4912
+		i += copy(dAtA[i:], m.CAKey)
4913
+	}
4914
+	if len(m.CrossSignedCACert) > 0 {
4915
+		dAtA[i] = 0x1a
4916
+		i++
4917
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.CrossSignedCACert)))
4918
+		i += copy(dAtA[i:], m.CrossSignedCACert)
4919
+	}
4920
+	return i, nil
4921
+}
4922
+
4887 4923
 func encodeFixed64Types(dAtA []byte, offset int, v uint64) int {
4888 4924
 	dAtA[offset] = uint8(v)
4889 4925
 	dAtA[offset+1] = uint8(v >> 8)
... ...
@@ -4921,6 +5143,20 @@ func (m *Version) Size() (n int) {
4921 4921
 	return n
4922 4922
 }
4923 4923
 
4924
+func (m *IndexEntry) Size() (n int) {
4925
+	var l int
4926
+	_ = l
4927
+	l = len(m.Key)
4928
+	if l > 0 {
4929
+		n += 1 + l + sovTypes(uint64(l))
4930
+	}
4931
+	l = len(m.Val)
4932
+	if l > 0 {
4933
+		n += 1 + l + sovTypes(uint64(l))
4934
+	}
4935
+	return n
4936
+}
4937
+
4924 4938
 func (m *Annotations) Size() (n int) {
4925 4939
 	var l int
4926 4940
 	_ = l
... ...
@@ -4936,6 +5172,12 @@ func (m *Annotations) Size() (n int) {
4936 4936
 			n += mapEntrySize + 1 + sovTypes(uint64(mapEntrySize))
4937 4937
 		}
4938 4938
 	}
4939
+	if len(m.Indices) > 0 {
4940
+		for _, e := range m.Indices {
4941
+			l = e.Size()
4942
+			n += 1 + l + sovTypes(uint64(l))
4943
+		}
4944
+	}
4939 4945
 	return n
4940 4946
 }
4941 4947
 
... ...
@@ -5194,6 +5436,9 @@ func (m *UpdateConfig) Size() (n int) {
5194 5194
 	if m.MaxFailureRatio != 0 {
5195 5195
 		n += 5
5196 5196
 	}
5197
+	if m.Order != 0 {
5198
+		n += 1 + sovTypes(uint64(m.Order))
5199
+	}
5197 5200
 	return n
5198 5201
 }
5199 5202
 
... ...
@@ -5490,6 +5735,10 @@ func (m *ExternalCA) Size() (n int) {
5490 5490
 			n += mapEntrySize + 1 + sovTypes(uint64(mapEntrySize))
5491 5491
 		}
5492 5492
 	}
5493
+	l = len(m.CACert)
5494
+	if l > 0 {
5495
+		n += 1 + l + sovTypes(uint64(l))
5496
+	}
5493 5497
 	return n
5494 5498
 }
5495 5499
 
... ...
@@ -5645,6 +5894,10 @@ func (m *RootCA) Size() (n int) {
5645 5645
 	}
5646 5646
 	l = m.JoinTokens.Size()
5647 5647
 	n += 1 + l + sovTypes(uint64(l))
5648
+	if m.RootRotation != nil {
5649
+		l = m.RootRotation.Size()
5650
+		n += 1 + l + sovTypes(uint64(l))
5651
+	}
5648 5652
 	return n
5649 5653
 }
5650 5654
 
... ...
@@ -5787,6 +6040,10 @@ func (m *HealthConfig) Size() (n int) {
5787 5787
 	if m.Retries != 0 {
5788 5788
 		n += 1 + sovTypes(uint64(m.Retries))
5789 5789
 	}
5790
+	if m.StartPeriod != nil {
5791
+		l = m.StartPeriod.Size()
5792
+		n += 1 + l + sovTypes(uint64(l))
5793
+	}
5790 5794
 	return n
5791 5795
 }
5792 5796
 
... ...
@@ -5807,6 +6064,24 @@ func (m *MaybeEncryptedRecord) Size() (n int) {
5807 5807
 	return n
5808 5808
 }
5809 5809
 
5810
+func (m *RootRotation) Size() (n int) {
5811
+	var l int
5812
+	_ = l
5813
+	l = len(m.CACert)
5814
+	if l > 0 {
5815
+		n += 1 + l + sovTypes(uint64(l))
5816
+	}
5817
+	l = len(m.CAKey)
5818
+	if l > 0 {
5819
+		n += 1 + l + sovTypes(uint64(l))
5820
+	}
5821
+	l = len(m.CrossSignedCACert)
5822
+	if l > 0 {
5823
+		n += 1 + l + sovTypes(uint64(l))
5824
+	}
5825
+	return n
5826
+}
5827
+
5810 5828
 func sovTypes(x uint64) (n int) {
5811 5829
 	for {
5812 5830
 		n++
... ...
@@ -5830,6 +6105,17 @@ func (this *Version) String() string {
5830 5830
 	}, "")
5831 5831
 	return s
5832 5832
 }
5833
+func (this *IndexEntry) String() string {
5834
+	if this == nil {
5835
+		return "nil"
5836
+	}
5837
+	s := strings.Join([]string{`&IndexEntry{`,
5838
+		`Key:` + fmt.Sprintf("%v", this.Key) + `,`,
5839
+		`Val:` + fmt.Sprintf("%v", this.Val) + `,`,
5840
+		`}`,
5841
+	}, "")
5842
+	return s
5843
+}
5833 5844
 func (this *Annotations) String() string {
5834 5845
 	if this == nil {
5835 5846
 		return "nil"
... ...
@@ -5847,6 +6133,7 @@ func (this *Annotations) String() string {
5847 5847
 	s := strings.Join([]string{`&Annotations{`,
5848 5848
 		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
5849 5849
 		`Labels:` + mapStringForLabels + `,`,
5850
+		`Indices:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Indices), "IndexEntry", "IndexEntry", 1), `&`, ``, 1) + `,`,
5850 5851
 		`}`,
5851 5852
 	}, "")
5852 5853
 	return s
... ...
@@ -6046,6 +6333,7 @@ func (this *UpdateConfig) String() string {
6046 6046
 		`FailureAction:` + fmt.Sprintf("%v", this.FailureAction) + `,`,
6047 6047
 		`Monitor:` + strings.Replace(fmt.Sprintf("%v", this.Monitor), "Duration", "google_protobuf1.Duration", 1) + `,`,
6048 6048
 		`MaxFailureRatio:` + fmt.Sprintf("%v", this.MaxFailureRatio) + `,`,
6049
+		`Order:` + fmt.Sprintf("%v", this.Order) + `,`,
6049 6050
 		`}`,
6050 6051
 	}, "")
6051 6052
 	return s
... ...
@@ -6276,6 +6564,7 @@ func (this *ExternalCA) String() string {
6276 6276
 		`Protocol:` + fmt.Sprintf("%v", this.Protocol) + `,`,
6277 6277
 		`URL:` + fmt.Sprintf("%v", this.URL) + `,`,
6278 6278
 		`Options:` + mapStringForOptions + `,`,
6279
+		`CACert:` + fmt.Sprintf("%v", this.CACert) + `,`,
6279 6280
 		`}`,
6280 6281
 	}, "")
6281 6282
 	return s
... ...
@@ -6406,6 +6695,7 @@ func (this *RootCA) String() string {
6406 6406
 		`CACert:` + fmt.Sprintf("%v", this.CACert) + `,`,
6407 6407
 		`CACertHash:` + fmt.Sprintf("%v", this.CACertHash) + `,`,
6408 6408
 		`JoinTokens:` + strings.Replace(strings.Replace(this.JoinTokens.String(), "JoinTokens", "JoinTokens", 1), `&`, ``, 1) + `,`,
6409
+		`RootRotation:` + strings.Replace(fmt.Sprintf("%v", this.RootRotation), "RootRotation", "RootRotation", 1) + `,`,
6409 6410
 		`}`,
6410 6411
 	}, "")
6411 6412
 	return s
... ...
@@ -6504,6 +6794,7 @@ func (this *HealthConfig) String() string {
6504 6504
 		`Interval:` + strings.Replace(fmt.Sprintf("%v", this.Interval), "Duration", "google_protobuf1.Duration", 1) + `,`,
6505 6505
 		`Timeout:` + strings.Replace(fmt.Sprintf("%v", this.Timeout), "Duration", "google_protobuf1.Duration", 1) + `,`,
6506 6506
 		`Retries:` + fmt.Sprintf("%v", this.Retries) + `,`,
6507
+		`StartPeriod:` + strings.Replace(fmt.Sprintf("%v", this.StartPeriod), "Duration", "google_protobuf1.Duration", 1) + `,`,
6507 6508
 		`}`,
6508 6509
 	}, "")
6509 6510
 	return s
... ...
@@ -6520,6 +6811,18 @@ func (this *MaybeEncryptedRecord) String() string {
6520 6520
 	}, "")
6521 6521
 	return s
6522 6522
 }
6523
+func (this *RootRotation) String() string {
6524
+	if this == nil {
6525
+		return "nil"
6526
+	}
6527
+	s := strings.Join([]string{`&RootRotation{`,
6528
+		`CACert:` + fmt.Sprintf("%v", this.CACert) + `,`,
6529
+		`CAKey:` + fmt.Sprintf("%v", this.CAKey) + `,`,
6530
+		`CrossSignedCACert:` + fmt.Sprintf("%v", this.CrossSignedCACert) + `,`,
6531
+		`}`,
6532
+	}, "")
6533
+	return s
6534
+}
6523 6535
 func valueToStringTypes(v interface{}) string {
6524 6536
 	rv := reflect.ValueOf(v)
6525 6537
 	if rv.IsNil() {
... ...
@@ -6597,6 +6900,114 @@ func (m *Version) Unmarshal(dAtA []byte) error {
6597 6597
 	}
6598 6598
 	return nil
6599 6599
 }
6600
+func (m *IndexEntry) Unmarshal(dAtA []byte) error {
6601
+	l := len(dAtA)
6602
+	iNdEx := 0
6603
+	for iNdEx < l {
6604
+		preIndex := iNdEx
6605
+		var wire uint64
6606
+		for shift := uint(0); ; shift += 7 {
6607
+			if shift >= 64 {
6608
+				return ErrIntOverflowTypes
6609
+			}
6610
+			if iNdEx >= l {
6611
+				return io.ErrUnexpectedEOF
6612
+			}
6613
+			b := dAtA[iNdEx]
6614
+			iNdEx++
6615
+			wire |= (uint64(b) & 0x7F) << shift
6616
+			if b < 0x80 {
6617
+				break
6618
+			}
6619
+		}
6620
+		fieldNum := int32(wire >> 3)
6621
+		wireType := int(wire & 0x7)
6622
+		if wireType == 4 {
6623
+			return fmt.Errorf("proto: IndexEntry: wiretype end group for non-group")
6624
+		}
6625
+		if fieldNum <= 0 {
6626
+			return fmt.Errorf("proto: IndexEntry: illegal tag %d (wire type %d)", fieldNum, wire)
6627
+		}
6628
+		switch fieldNum {
6629
+		case 1:
6630
+			if wireType != 2 {
6631
+				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
6632
+			}
6633
+			var stringLen uint64
6634
+			for shift := uint(0); ; shift += 7 {
6635
+				if shift >= 64 {
6636
+					return ErrIntOverflowTypes
6637
+				}
6638
+				if iNdEx >= l {
6639
+					return io.ErrUnexpectedEOF
6640
+				}
6641
+				b := dAtA[iNdEx]
6642
+				iNdEx++
6643
+				stringLen |= (uint64(b) & 0x7F) << shift
6644
+				if b < 0x80 {
6645
+					break
6646
+				}
6647
+			}
6648
+			intStringLen := int(stringLen)
6649
+			if intStringLen < 0 {
6650
+				return ErrInvalidLengthTypes
6651
+			}
6652
+			postIndex := iNdEx + intStringLen
6653
+			if postIndex > l {
6654
+				return io.ErrUnexpectedEOF
6655
+			}
6656
+			m.Key = string(dAtA[iNdEx:postIndex])
6657
+			iNdEx = postIndex
6658
+		case 2:
6659
+			if wireType != 2 {
6660
+				return fmt.Errorf("proto: wrong wireType = %d for field Val", wireType)
6661
+			}
6662
+			var stringLen uint64
6663
+			for shift := uint(0); ; shift += 7 {
6664
+				if shift >= 64 {
6665
+					return ErrIntOverflowTypes
6666
+				}
6667
+				if iNdEx >= l {
6668
+					return io.ErrUnexpectedEOF
6669
+				}
6670
+				b := dAtA[iNdEx]
6671
+				iNdEx++
6672
+				stringLen |= (uint64(b) & 0x7F) << shift
6673
+				if b < 0x80 {
6674
+					break
6675
+				}
6676
+			}
6677
+			intStringLen := int(stringLen)
6678
+			if intStringLen < 0 {
6679
+				return ErrInvalidLengthTypes
6680
+			}
6681
+			postIndex := iNdEx + intStringLen
6682
+			if postIndex > l {
6683
+				return io.ErrUnexpectedEOF
6684
+			}
6685
+			m.Val = string(dAtA[iNdEx:postIndex])
6686
+			iNdEx = postIndex
6687
+		default:
6688
+			iNdEx = preIndex
6689
+			skippy, err := skipTypes(dAtA[iNdEx:])
6690
+			if err != nil {
6691
+				return err
6692
+			}
6693
+			if skippy < 0 {
6694
+				return ErrInvalidLengthTypes
6695
+			}
6696
+			if (iNdEx + skippy) > l {
6697
+				return io.ErrUnexpectedEOF
6698
+			}
6699
+			iNdEx += skippy
6700
+		}
6701
+	}
6702
+
6703
+	if iNdEx > l {
6704
+		return io.ErrUnexpectedEOF
6705
+	}
6706
+	return nil
6707
+}
6600 6708
 func (m *Annotations) Unmarshal(dAtA []byte) error {
6601 6709
 	l := len(dAtA)
6602 6710
 	iNdEx := 0
... ...
@@ -6771,6 +7182,37 @@ func (m *Annotations) Unmarshal(dAtA []byte) error {
6771 6771
 				m.Labels[mapkey] = mapvalue
6772 6772
 			}
6773 6773
 			iNdEx = postIndex
6774
+		case 4:
6775
+			if wireType != 2 {
6776
+				return fmt.Errorf("proto: wrong wireType = %d for field Indices", wireType)
6777
+			}
6778
+			var msglen int
6779
+			for shift := uint(0); ; shift += 7 {
6780
+				if shift >= 64 {
6781
+					return ErrIntOverflowTypes
6782
+				}
6783
+				if iNdEx >= l {
6784
+					return io.ErrUnexpectedEOF
6785
+				}
6786
+				b := dAtA[iNdEx]
6787
+				iNdEx++
6788
+				msglen |= (int(b) & 0x7F) << shift
6789
+				if b < 0x80 {
6790
+					break
6791
+				}
6792
+			}
6793
+			if msglen < 0 {
6794
+				return ErrInvalidLengthTypes
6795
+			}
6796
+			postIndex := iNdEx + msglen
6797
+			if postIndex > l {
6798
+				return io.ErrUnexpectedEOF
6799
+			}
6800
+			m.Indices = append(m.Indices, IndexEntry{})
6801
+			if err := m.Indices[len(m.Indices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
6802
+				return err
6803
+			}
6804
+			iNdEx = postIndex
6774 6805
 		default:
6775 6806
 			iNdEx = preIndex
6776 6807
 			skippy, err := skipTypes(dAtA[iNdEx:])
... ...
@@ -8860,6 +9302,25 @@ func (m *UpdateConfig) Unmarshal(dAtA []byte) error {
8860 8860
 			v |= uint32(dAtA[iNdEx-2]) << 16
8861 8861
 			v |= uint32(dAtA[iNdEx-1]) << 24
8862 8862
 			m.MaxFailureRatio = float32(math.Float32frombits(v))
8863
+		case 6:
8864
+			if wireType != 0 {
8865
+				return fmt.Errorf("proto: wrong wireType = %d for field Order", wireType)
8866
+			}
8867
+			m.Order = 0
8868
+			for shift := uint(0); ; shift += 7 {
8869
+				if shift >= 64 {
8870
+					return ErrIntOverflowTypes
8871
+				}
8872
+				if iNdEx >= l {
8873
+					return io.ErrUnexpectedEOF
8874
+				}
8875
+				b := dAtA[iNdEx]
8876
+				iNdEx++
8877
+				m.Order |= (UpdateConfig_UpdateOrder(b) & 0x7F) << shift
8878
+				if b < 0x80 {
8879
+					break
8880
+				}
8881
+			}
8863 8882
 		default:
8864 8883
 			iNdEx = preIndex
8865 8884
 			skippy, err := skipTypes(dAtA[iNdEx:])
... ...
@@ -11155,6 +11616,37 @@ func (m *ExternalCA) Unmarshal(dAtA []byte) error {
11155 11155
 				m.Options[mapkey] = mapvalue
11156 11156
 			}
11157 11157
 			iNdEx = postIndex
11158
+		case 4:
11159
+			if wireType != 2 {
11160
+				return fmt.Errorf("proto: wrong wireType = %d for field CACert", wireType)
11161
+			}
11162
+			var byteLen int
11163
+			for shift := uint(0); ; shift += 7 {
11164
+				if shift >= 64 {
11165
+					return ErrIntOverflowTypes
11166
+				}
11167
+				if iNdEx >= l {
11168
+					return io.ErrUnexpectedEOF
11169
+				}
11170
+				b := dAtA[iNdEx]
11171
+				iNdEx++
11172
+				byteLen |= (int(b) & 0x7F) << shift
11173
+				if b < 0x80 {
11174
+					break
11175
+				}
11176
+			}
11177
+			if byteLen < 0 {
11178
+				return ErrInvalidLengthTypes
11179
+			}
11180
+			postIndex := iNdEx + byteLen
11181
+			if postIndex > l {
11182
+				return io.ErrUnexpectedEOF
11183
+			}
11184
+			m.CACert = append(m.CACert[:0], dAtA[iNdEx:postIndex]...)
11185
+			if m.CACert == nil {
11186
+				m.CACert = []byte{}
11187
+			}
11188
+			iNdEx = postIndex
11158 11189
 		default:
11159 11190
 			iNdEx = preIndex
11160 11191
 			skippy, err := skipTypes(dAtA[iNdEx:])
... ...
@@ -12269,6 +12761,39 @@ func (m *RootCA) Unmarshal(dAtA []byte) error {
12269 12269
 				return err
12270 12270
 			}
12271 12271
 			iNdEx = postIndex
12272
+		case 5:
12273
+			if wireType != 2 {
12274
+				return fmt.Errorf("proto: wrong wireType = %d for field RootRotation", wireType)
12275
+			}
12276
+			var msglen int
12277
+			for shift := uint(0); ; shift += 7 {
12278
+				if shift >= 64 {
12279
+					return ErrIntOverflowTypes
12280
+				}
12281
+				if iNdEx >= l {
12282
+					return io.ErrUnexpectedEOF
12283
+				}
12284
+				b := dAtA[iNdEx]
12285
+				iNdEx++
12286
+				msglen |= (int(b) & 0x7F) << shift
12287
+				if b < 0x80 {
12288
+					break
12289
+				}
12290
+			}
12291
+			if msglen < 0 {
12292
+				return ErrInvalidLengthTypes
12293
+			}
12294
+			postIndex := iNdEx + msglen
12295
+			if postIndex > l {
12296
+				return io.ErrUnexpectedEOF
12297
+			}
12298
+			if m.RootRotation == nil {
12299
+				m.RootRotation = &RootRotation{}
12300
+			}
12301
+			if err := m.RootRotation.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
12302
+				return err
12303
+			}
12304
+			iNdEx = postIndex
12272 12305
 		default:
12273 12306
 			iNdEx = preIndex
12274 12307
 			skippy, err := skipTypes(dAtA[iNdEx:])
... ...
@@ -13287,6 +13812,39 @@ func (m *HealthConfig) Unmarshal(dAtA []byte) error {
13287 13287
 					break
13288 13288
 				}
13289 13289
 			}
13290
+		case 5:
13291
+			if wireType != 2 {
13292
+				return fmt.Errorf("proto: wrong wireType = %d for field StartPeriod", wireType)
13293
+			}
13294
+			var msglen int
13295
+			for shift := uint(0); ; shift += 7 {
13296
+				if shift >= 64 {
13297
+					return ErrIntOverflowTypes
13298
+				}
13299
+				if iNdEx >= l {
13300
+					return io.ErrUnexpectedEOF
13301
+				}
13302
+				b := dAtA[iNdEx]
13303
+				iNdEx++
13304
+				msglen |= (int(b) & 0x7F) << shift
13305
+				if b < 0x80 {
13306
+					break
13307
+				}
13308
+			}
13309
+			if msglen < 0 {
13310
+				return ErrInvalidLengthTypes
13311
+			}
13312
+			postIndex := iNdEx + msglen
13313
+			if postIndex > l {
13314
+				return io.ErrUnexpectedEOF
13315
+			}
13316
+			if m.StartPeriod == nil {
13317
+				m.StartPeriod = &google_protobuf1.Duration{}
13318
+			}
13319
+			if err := m.StartPeriod.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
13320
+				return err
13321
+			}
13322
+			iNdEx = postIndex
13290 13323
 		default:
13291 13324
 			iNdEx = preIndex
13292 13325
 			skippy, err := skipTypes(dAtA[iNdEx:])
... ...
@@ -13439,6 +13997,149 @@ func (m *MaybeEncryptedRecord) Unmarshal(dAtA []byte) error {
13439 13439
 	}
13440 13440
 	return nil
13441 13441
 }
13442
+func (m *RootRotation) Unmarshal(dAtA []byte) error {
13443
+	l := len(dAtA)
13444
+	iNdEx := 0
13445
+	for iNdEx < l {
13446
+		preIndex := iNdEx
13447
+		var wire uint64
13448
+		for shift := uint(0); ; shift += 7 {
13449
+			if shift >= 64 {
13450
+				return ErrIntOverflowTypes
13451
+			}
13452
+			if iNdEx >= l {
13453
+				return io.ErrUnexpectedEOF
13454
+			}
13455
+			b := dAtA[iNdEx]
13456
+			iNdEx++
13457
+			wire |= (uint64(b) & 0x7F) << shift
13458
+			if b < 0x80 {
13459
+				break
13460
+			}
13461
+		}
13462
+		fieldNum := int32(wire >> 3)
13463
+		wireType := int(wire & 0x7)
13464
+		if wireType == 4 {
13465
+			return fmt.Errorf("proto: RootRotation: wiretype end group for non-group")
13466
+		}
13467
+		if fieldNum <= 0 {
13468
+			return fmt.Errorf("proto: RootRotation: illegal tag %d (wire type %d)", fieldNum, wire)
13469
+		}
13470
+		switch fieldNum {
13471
+		case 1:
13472
+			if wireType != 2 {
13473
+				return fmt.Errorf("proto: wrong wireType = %d for field CACert", wireType)
13474
+			}
13475
+			var byteLen int
13476
+			for shift := uint(0); ; shift += 7 {
13477
+				if shift >= 64 {
13478
+					return ErrIntOverflowTypes
13479
+				}
13480
+				if iNdEx >= l {
13481
+					return io.ErrUnexpectedEOF
13482
+				}
13483
+				b := dAtA[iNdEx]
13484
+				iNdEx++
13485
+				byteLen |= (int(b) & 0x7F) << shift
13486
+				if b < 0x80 {
13487
+					break
13488
+				}
13489
+			}
13490
+			if byteLen < 0 {
13491
+				return ErrInvalidLengthTypes
13492
+			}
13493
+			postIndex := iNdEx + byteLen
13494
+			if postIndex > l {
13495
+				return io.ErrUnexpectedEOF
13496
+			}
13497
+			m.CACert = append(m.CACert[:0], dAtA[iNdEx:postIndex]...)
13498
+			if m.CACert == nil {
13499
+				m.CACert = []byte{}
13500
+			}
13501
+			iNdEx = postIndex
13502
+		case 2:
13503
+			if wireType != 2 {
13504
+				return fmt.Errorf("proto: wrong wireType = %d for field CAKey", wireType)
13505
+			}
13506
+			var byteLen int
13507
+			for shift := uint(0); ; shift += 7 {
13508
+				if shift >= 64 {
13509
+					return ErrIntOverflowTypes
13510
+				}
13511
+				if iNdEx >= l {
13512
+					return io.ErrUnexpectedEOF
13513
+				}
13514
+				b := dAtA[iNdEx]
13515
+				iNdEx++
13516
+				byteLen |= (int(b) & 0x7F) << shift
13517
+				if b < 0x80 {
13518
+					break
13519
+				}
13520
+			}
13521
+			if byteLen < 0 {
13522
+				return ErrInvalidLengthTypes
13523
+			}
13524
+			postIndex := iNdEx + byteLen
13525
+			if postIndex > l {
13526
+				return io.ErrUnexpectedEOF
13527
+			}
13528
+			m.CAKey = append(m.CAKey[:0], dAtA[iNdEx:postIndex]...)
13529
+			if m.CAKey == nil {
13530
+				m.CAKey = []byte{}
13531
+			}
13532
+			iNdEx = postIndex
13533
+		case 3:
13534
+			if wireType != 2 {
13535
+				return fmt.Errorf("proto: wrong wireType = %d for field CrossSignedCACert", wireType)
13536
+			}
13537
+			var byteLen int
13538
+			for shift := uint(0); ; shift += 7 {
13539
+				if shift >= 64 {
13540
+					return ErrIntOverflowTypes
13541
+				}
13542
+				if iNdEx >= l {
13543
+					return io.ErrUnexpectedEOF
13544
+				}
13545
+				b := dAtA[iNdEx]
13546
+				iNdEx++
13547
+				byteLen |= (int(b) & 0x7F) << shift
13548
+				if b < 0x80 {
13549
+					break
13550
+				}
13551
+			}
13552
+			if byteLen < 0 {
13553
+				return ErrInvalidLengthTypes
13554
+			}
13555
+			postIndex := iNdEx + byteLen
13556
+			if postIndex > l {
13557
+				return io.ErrUnexpectedEOF
13558
+			}
13559
+			m.CrossSignedCACert = append(m.CrossSignedCACert[:0], dAtA[iNdEx:postIndex]...)
13560
+			if m.CrossSignedCACert == nil {
13561
+				m.CrossSignedCACert = []byte{}
13562
+			}
13563
+			iNdEx = postIndex
13564
+		default:
13565
+			iNdEx = preIndex
13566
+			skippy, err := skipTypes(dAtA[iNdEx:])
13567
+			if err != nil {
13568
+				return err
13569
+			}
13570
+			if skippy < 0 {
13571
+				return ErrInvalidLengthTypes
13572
+			}
13573
+			if (iNdEx + skippy) > l {
13574
+				return io.ErrUnexpectedEOF
13575
+			}
13576
+			iNdEx += skippy
13577
+		}
13578
+	}
13579
+
13580
+	if iNdEx > l {
13581
+		return io.ErrUnexpectedEOF
13582
+	}
13583
+	return nil
13584
+}
13442 13585
 func skipTypes(dAtA []byte) (n int, err error) {
13443 13586
 	l := len(dAtA)
13444 13587
 	iNdEx := 0
... ...
@@ -13547,259 +14248,271 @@ var (
13547 13547
 func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) }
13548 13548
 
13549 13549
 var fileDescriptorTypes = []byte{
13550
-	// 4064 bytes of a gzipped FileDescriptorProto
13551
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x5a, 0x4d, 0x6c, 0x1b, 0x49,
13552
-	0x76, 0x16, 0x7f, 0x45, 0x3e, 0x52, 0x52, 0xbb, 0xec, 0xf5, 0xca, 0x1c, 0x8f, 0xc4, 0xe9, 0x19,
13553
-	0xef, 0x78, 0xbc, 0x06, 0xc7, 0x96, 0x77, 0x16, 0x9e, 0x31, 0x76, 0x3d, 0xcd, 0x1f, 0x5b, 0x5c,
13554
-	0x4b, 0x24, 0x51, 0xa4, 0xec, 0x9d, 0x43, 0x42, 0x94, 0xba, 0x4b, 0x54, 0x8f, 0x9a, 0x5d, 0x4c,
13555
-	0x77, 0x53, 0x32, 0x13, 0x04, 0x31, 0x72, 0x48, 0x02, 0x9d, 0x72, 0x0c, 0x10, 0x08, 0x41, 0xb0,
13556
-	0x39, 0x04, 0x39, 0xe4, 0x92, 0x43, 0x80, 0x5c, 0x32, 0xc7, 0x39, 0x6e, 0x12, 0x20, 0x58, 0x64,
13557
-	0x01, 0x27, 0xab, 0x9c, 0x83, 0xe4, 0xb2, 0xc8, 0x25, 0x01, 0x82, 0xfa, 0xe9, 0x66, 0x93, 0xa6,
13558
-	0x65, 0x4f, 0x76, 0x2f, 0x52, 0xd7, 0xab, 0xef, 0xbd, 0xfa, 0x79, 0xaf, 0xaa, 0xbe, 0x57, 0x45,
13559
-	0x28, 0x04, 0x93, 0x11, 0xf5, 0x2b, 0x23, 0x8f, 0x05, 0x0c, 0x21, 0x8b, 0x99, 0x47, 0xd4, 0xab,
13560
-	0xf8, 0x27, 0xc4, 0x1b, 0x1e, 0xd9, 0x41, 0xe5, 0xf8, 0x6e, 0x69, 0x73, 0xc0, 0xd8, 0xc0, 0xa1,
13561
-	0x1f, 0x0b, 0xc4, 0xfe, 0xf8, 0xe0, 0xe3, 0xc0, 0x1e, 0x52, 0x3f, 0x20, 0xc3, 0x91, 0x54, 0x2a,
13562
-	0x6d, 0xcc, 0x03, 0xac, 0xb1, 0x47, 0x02, 0x9b, 0xb9, 0xaa, 0xfe, 0xca, 0x80, 0x0d, 0x98, 0xf8,
13563
-	0xfc, 0x98, 0x7f, 0x49, 0xa9, 0xbe, 0x09, 0xcb, 0x4f, 0xa9, 0xe7, 0xdb, 0xcc, 0x45, 0x57, 0x20,
13564
-	0x63, 0xbb, 0x16, 0x7d, 0xbe, 0x9e, 0x28, 0x27, 0x6e, 0xa6, 0xb1, 0x2c, 0xe8, 0x7f, 0x9e, 0x80,
13565
-	0x82, 0xe1, 0xba, 0x2c, 0x10, 0xb6, 0x7c, 0x84, 0x20, 0xed, 0x92, 0x21, 0x15, 0xa0, 0x3c, 0x16,
13566
-	0xdf, 0xa8, 0x06, 0x59, 0x87, 0xec, 0x53, 0xc7, 0x5f, 0x4f, 0x96, 0x53, 0x37, 0x0b, 0x5b, 0xdf,
13567
-	0xad, 0xbc, 0x3a, 0x80, 0x4a, 0xcc, 0x48, 0x65, 0x47, 0xa0, 0x1b, 0x6e, 0xe0, 0x4d, 0xb0, 0x52,
13568
-	0x2d, 0x7d, 0x0a, 0x85, 0x98, 0x18, 0x69, 0x90, 0x3a, 0xa2, 0x13, 0xd5, 0x0c, 0xff, 0xe4, 0xfd,
13569
-	0x3b, 0x26, 0xce, 0x98, 0xae, 0x27, 0x85, 0x4c, 0x16, 0x3e, 0x4b, 0xde, 0x4f, 0xe8, 0x5f, 0x40,
13570
-	0x1e, 0x53, 0x9f, 0x8d, 0x3d, 0x93, 0xfa, 0xe8, 0x23, 0xc8, 0xbb, 0xc4, 0x65, 0x7d, 0x73, 0x34,
13571
-	0xf6, 0x85, 0x7a, 0xaa, 0x5a, 0x3c, 0x7f, 0xb9, 0x99, 0x6b, 0x11, 0x97, 0xd5, 0x3a, 0x7b, 0x3e,
13572
-	0xce, 0xf1, 0xea, 0xda, 0x68, 0xec, 0xa3, 0xf7, 0xa0, 0x38, 0xa4, 0x43, 0xe6, 0x4d, 0xfa, 0xfb,
13573
-	0x93, 0x80, 0xfa, 0xc2, 0x70, 0x0a, 0x17, 0xa4, 0xac, 0xca, 0x45, 0xfa, 0x1f, 0x27, 0xe0, 0x4a,
13574
-	0x68, 0x1b, 0xd3, 0xdf, 0x1a, 0xdb, 0x1e, 0x1d, 0x52, 0x37, 0xf0, 0xd1, 0x27, 0x90, 0x75, 0xec,
13575
-	0xa1, 0x1d, 0xc8, 0x36, 0x0a, 0x5b, 0xef, 0x2e, 0x1a, 0x73, 0xd4, 0x2b, 0xac, 0xc0, 0xc8, 0x80,
13576
-	0xa2, 0x47, 0x7d, 0xea, 0x1d, 0xcb, 0x99, 0x10, 0x4d, 0xbe, 0x51, 0x79, 0x46, 0x45, 0x7f, 0x04,
13577
-	0xb9, 0x8e, 0x43, 0x82, 0x03, 0xe6, 0x0d, 0x91, 0x0e, 0x45, 0xe2, 0x99, 0x87, 0x76, 0x40, 0xcd,
13578
-	0x60, 0xec, 0x85, 0x5e, 0x99, 0x91, 0xa1, 0xab, 0x90, 0x64, 0xb2, 0xa1, 0x7c, 0x35, 0x7b, 0xfe,
13579
-	0x72, 0x33, 0xd9, 0xee, 0xe2, 0x24, 0xf3, 0xf5, 0x07, 0x70, 0xa9, 0xe3, 0x8c, 0x07, 0xb6, 0x5b,
13580
-	0xa7, 0xbe, 0xe9, 0xd9, 0x23, 0x6e, 0x9d, 0xbb, 0x97, 0x47, 0x62, 0xe8, 0x5e, 0xfe, 0x1d, 0xb9,
13581
-	0x3c, 0x39, 0x75, 0xb9, 0xfe, 0x87, 0x49, 0xb8, 0xd4, 0x70, 0x07, 0xb6, 0x4b, 0xe3, 0xda, 0x37,
13582
-	0x60, 0x95, 0x0a, 0x61, 0xff, 0x58, 0x06, 0x95, 0xb2, 0xb3, 0x22, 0xa5, 0x61, 0xa4, 0x35, 0xe7,
13583
-	0xe2, 0xe5, 0xee, 0xa2, 0xe1, 0xbf, 0x62, 0x7d, 0x51, 0xd4, 0xa0, 0x06, 0x2c, 0x8f, 0xc4, 0x20,
13584
-	0xfc, 0xf5, 0x94, 0xb0, 0x75, 0x63, 0x91, 0xad, 0x57, 0xc6, 0x59, 0x4d, 0x7f, 0xfd, 0x72, 0x73,
13585
-	0x09, 0x87, 0xba, 0xbf, 0x4a, 0xf0, 0xfd, 0x7b, 0x02, 0xd6, 0x5a, 0xcc, 0x9a, 0x99, 0x87, 0x12,
13586
-	0xe4, 0x0e, 0x99, 0x1f, 0xc4, 0x16, 0x4a, 0x54, 0x46, 0xf7, 0x21, 0x37, 0x52, 0xee, 0x53, 0xde,
13587
-	0xbf, 0xbe, 0xb8, 0xcb, 0x12, 0x83, 0x23, 0x34, 0x7a, 0x00, 0x79, 0x2f, 0x8c, 0x89, 0xf5, 0xd4,
13588
-	0xdb, 0x04, 0xce, 0x14, 0x8f, 0x7e, 0x00, 0x59, 0xe9, 0x84, 0xf5, 0xb4, 0xd0, 0xbc, 0xf1, 0x56,
13589
-	0x73, 0x8e, 0x95, 0x92, 0xfe, 0xb3, 0x04, 0x68, 0x98, 0x1c, 0x04, 0xbb, 0x74, 0xb8, 0x4f, 0xbd,
13590
-	0x6e, 0x40, 0x82, 0xb1, 0x8f, 0xae, 0x42, 0xd6, 0xa1, 0xc4, 0xa2, 0x9e, 0x18, 0x64, 0x0e, 0xab,
13591
-	0x12, 0xda, 0xe3, 0x41, 0x4e, 0xcc, 0x43, 0xb2, 0x6f, 0x3b, 0x76, 0x30, 0x11, 0xc3, 0x5c, 0x5d,
13592
-	0xec, 0xe5, 0x79, 0x9b, 0x15, 0x1c, 0x53, 0xc4, 0x33, 0x66, 0xd0, 0x3a, 0x2c, 0x0f, 0xa9, 0xef,
13593
-	0x93, 0x01, 0x15, 0xa3, 0xcf, 0xe3, 0xb0, 0xa8, 0x3f, 0x80, 0x62, 0x5c, 0x0f, 0x15, 0x60, 0x79,
13594
-	0xaf, 0xf5, 0xa4, 0xd5, 0x7e, 0xd6, 0xd2, 0x96, 0xd0, 0x1a, 0x14, 0xf6, 0x5a, 0xb8, 0x61, 0xd4,
13595
-	0xb6, 0x8d, 0xea, 0x4e, 0x43, 0x4b, 0xa0, 0x15, 0xc8, 0x4f, 0x8b, 0x49, 0xfd, 0x6f, 0x12, 0x00,
13596
-	0xdc, 0x81, 0x6a, 0x50, 0x9f, 0x41, 0xc6, 0x0f, 0x48, 0x20, 0x1d, 0xb7, 0xba, 0xf5, 0xc1, 0xa2,
13597
-	0x5e, 0x4f, 0xe1, 0x15, 0xfe, 0x8f, 0x62, 0xa9, 0x12, 0xef, 0x61, 0x72, 0xa6, 0x87, 0x7c, 0x0d,
13598
-	0x11, 0xcb, 0xf2, 0x54, 0xc7, 0xc5, 0xb7, 0xfe, 0x00, 0x32, 0x42, 0x7b, 0xb6, 0xbb, 0x39, 0x48,
13599
-	0xd7, 0xf9, 0x57, 0x02, 0xe5, 0x21, 0x83, 0x1b, 0x46, 0xfd, 0x0b, 0x2d, 0x89, 0x34, 0x28, 0xd6,
13600
-	0x9b, 0xdd, 0x5a, 0xbb, 0xd5, 0x6a, 0xd4, 0x7a, 0x8d, 0xba, 0x96, 0xd2, 0x6f, 0x40, 0xa6, 0x39,
13601
-	0xe4, 0x96, 0xaf, 0xf3, 0xa8, 0x38, 0xa0, 0x1e, 0x75, 0xcd, 0x30, 0xd8, 0xa6, 0x02, 0xfd, 0xa7,
13602
-	0x79, 0xc8, 0xec, 0xb2, 0xb1, 0x1b, 0xa0, 0xad, 0xd8, 0xca, 0x5e, 0xdd, 0xda, 0x58, 0x34, 0x2c,
13603
-	0x01, 0xac, 0xf4, 0x26, 0x23, 0xaa, 0x56, 0xfe, 0x55, 0xc8, 0xca, 0xf8, 0x51, 0xc3, 0x51, 0x25,
13604
-	0x2e, 0x0f, 0x88, 0x37, 0xa0, 0x81, 0x1a, 0x8f, 0x2a, 0xa1, 0x9b, 0x90, 0xf3, 0x28, 0xb1, 0x98,
13605
-	0xeb, 0x4c, 0x44, 0x98, 0xe5, 0xe4, 0xd6, 0x8b, 0x29, 0xb1, 0xda, 0xae, 0x33, 0xc1, 0x51, 0x2d,
13606
-	0xda, 0x86, 0xe2, 0xbe, 0xed, 0x5a, 0x7d, 0x36, 0x92, 0xfb, 0x60, 0xe6, 0xf5, 0x41, 0x29, 0x7b,
13607
-	0x55, 0xb5, 0x5d, 0xab, 0x2d, 0xc1, 0xb8, 0xb0, 0x3f, 0x2d, 0xa0, 0x16, 0xac, 0x1e, 0x33, 0x67,
13608
-	0x3c, 0xa4, 0x91, 0xad, 0xac, 0xb0, 0xf5, 0xe1, 0xeb, 0x6d, 0x3d, 0x15, 0xf8, 0xd0, 0xda, 0xca,
13609
-	0x71, 0xbc, 0x88, 0x9e, 0xc0, 0x4a, 0x30, 0x1c, 0x1d, 0xf8, 0x91, 0xb9, 0x65, 0x61, 0xee, 0x3b,
13610
-	0x17, 0x4c, 0x18, 0x87, 0x87, 0xd6, 0x8a, 0x41, 0xac, 0x54, 0xfa, 0xfd, 0x14, 0x14, 0x62, 0x3d,
13611
-	0x47, 0x5d, 0x28, 0x8c, 0x3c, 0x36, 0x22, 0x03, 0xb1, 0x97, 0x2b, 0x5f, 0xdc, 0x7d, 0xab, 0x51,
13612
-	0x57, 0x3a, 0x53, 0x45, 0x1c, 0xb7, 0xa2, 0x9f, 0x25, 0xa1, 0x10, 0xab, 0x44, 0xb7, 0x20, 0x87,
13613
-	0x3b, 0xb8, 0xf9, 0xd4, 0xe8, 0x35, 0xb4, 0xa5, 0xd2, 0xf5, 0xd3, 0xb3, 0xf2, 0xba, 0xb0, 0x16,
13614
-	0x37, 0xd0, 0xf1, 0xec, 0x63, 0x1e, 0x7a, 0x37, 0x61, 0x39, 0x84, 0x26, 0x4a, 0xef, 0x9c, 0x9e,
13615
-	0x95, 0xbf, 0x3d, 0x0f, 0x8d, 0x21, 0x71, 0x77, 0xdb, 0xc0, 0x8d, 0xba, 0x96, 0x5c, 0x8c, 0xc4,
13616
-	0xdd, 0x43, 0xe2, 0x51, 0x0b, 0x7d, 0x07, 0xb2, 0x0a, 0x98, 0x2a, 0x95, 0x4e, 0xcf, 0xca, 0x57,
13617
-	0xe7, 0x81, 0x53, 0x1c, 0xee, 0xee, 0x18, 0x4f, 0x1b, 0x5a, 0x7a, 0x31, 0x0e, 0x77, 0x1d, 0x72,
13618
-	0x4c, 0xd1, 0x07, 0x90, 0x91, 0xb0, 0x4c, 0xe9, 0xda, 0xe9, 0x59, 0xf9, 0x5b, 0xaf, 0x98, 0xe3,
13619
-	0xa8, 0xd2, 0xfa, 0x1f, 0xfd, 0x64, 0x63, 0xe9, 0xef, 0xfe, 0x62, 0x43, 0x9b, 0xaf, 0x2e, 0xfd,
13620
-	0x4f, 0x02, 0x56, 0x66, 0x5c, 0x8e, 0x74, 0xc8, 0xba, 0xcc, 0x64, 0x23, 0xb9, 0xc5, 0xe7, 0xaa,
13621
-	0x70, 0xfe, 0x72, 0x33, 0xdb, 0x62, 0x35, 0x36, 0x9a, 0x60, 0x55, 0x83, 0x9e, 0xcc, 0x1d, 0x52,
13622
-	0xf7, 0xde, 0x32, 0x9e, 0x16, 0x1e, 0x53, 0x0f, 0x61, 0xc5, 0xf2, 0xec, 0x63, 0xea, 0xf5, 0x4d,
13623
-	0xe6, 0x1e, 0xd8, 0x03, 0xb5, 0x7d, 0x97, 0x16, 0xd9, 0xac, 0x0b, 0x20, 0x2e, 0x4a, 0x85, 0x9a,
13624
-	0xc0, 0xff, 0x0a, 0x07, 0x54, 0xe9, 0x29, 0x14, 0xe3, 0x11, 0x8a, 0xde, 0x05, 0xf0, 0xed, 0xdf,
13625
-	0xa6, 0x8a, 0xf3, 0x08, 0x86, 0x84, 0xf3, 0x5c, 0x22, 0x18, 0x0f, 0xfa, 0x10, 0xd2, 0x43, 0x66,
13626
-	0x49, 0x3b, 0x2b, 0xd5, 0xcb, 0xfc, 0x9c, 0xfc, 0x97, 0x97, 0x9b, 0x05, 0xe6, 0x57, 0x1e, 0xd9,
13627
-	0x0e, 0xdd, 0x65, 0x16, 0xc5, 0x02, 0xa0, 0x1f, 0x43, 0x9a, 0x6f, 0x15, 0xe8, 0x1d, 0x48, 0x57,
13628
-	0x9b, 0xad, 0xba, 0xb6, 0x54, 0xba, 0x74, 0x7a, 0x56, 0x5e, 0x11, 0x53, 0xc2, 0x2b, 0x78, 0xec,
13629
-	0xa2, 0x4d, 0xc8, 0x3e, 0x6d, 0xef, 0xec, 0xed, 0xf2, 0xf0, 0xba, 0x7c, 0x7a, 0x56, 0x5e, 0x8b,
13630
-	0xaa, 0xe5, 0xa4, 0xa1, 0x77, 0x21, 0xd3, 0xdb, 0xed, 0x3c, 0xea, 0x6a, 0xc9, 0x12, 0x3a, 0x3d,
13631
-	0x2b, 0xaf, 0x46, 0xf5, 0xa2, 0xcf, 0xa5, 0x4b, 0xca, 0xab, 0xf9, 0x48, 0xae, 0xff, 0x32, 0x09,
13632
-	0x2b, 0x98, 0x53, 0x5f, 0x2f, 0xe8, 0x30, 0xc7, 0x36, 0x27, 0xa8, 0x03, 0x79, 0x93, 0xb9, 0x96,
13633
-	0x1d, 0x5b, 0x53, 0x5b, 0xaf, 0x39, 0x18, 0xa7, 0x5a, 0x61, 0xa9, 0x16, 0x6a, 0xe2, 0xa9, 0x11,
13634
-	0xf4, 0x31, 0x64, 0x2c, 0xea, 0x90, 0x89, 0x3a, 0xa1, 0xaf, 0x55, 0x24, 0xb9, 0xae, 0x84, 0xe4,
13635
-	0xba, 0x52, 0x57, 0xe4, 0x1a, 0x4b, 0x9c, 0xa0, 0x92, 0xe4, 0x79, 0x9f, 0x04, 0x01, 0x1d, 0x8e,
13636
-	0x02, 0x79, 0x3c, 0xa7, 0x71, 0x61, 0x48, 0x9e, 0x1b, 0x4a, 0x84, 0xee, 0x42, 0xf6, 0xc4, 0x76,
13637
-	0x2d, 0x76, 0xa2, 0x4e, 0xe0, 0x0b, 0x8c, 0x2a, 0xa0, 0x7e, 0xca, 0x4f, 0xdd, 0xb9, 0x6e, 0xf2,
13638
-	0xf9, 0x6e, 0xb5, 0x5b, 0x8d, 0x70, 0xbe, 0x55, 0x7d, 0xdb, 0x6d, 0x31, 0x97, 0xaf, 0x15, 0x68,
13639
-	0xb7, 0xfa, 0x8f, 0x8c, 0xe6, 0xce, 0x1e, 0xe6, 0x73, 0x7e, 0xe5, 0xf4, 0xac, 0xac, 0x45, 0x90,
13640
-	0x47, 0xc4, 0x76, 0x38, 0x25, 0xbc, 0x06, 0x29, 0xa3, 0xf5, 0x85, 0x96, 0x2c, 0x69, 0xa7, 0x67,
13641
-	0xe5, 0x62, 0x54, 0x6d, 0xb8, 0x93, 0xe9, 0x32, 0x9a, 0x6f, 0x57, 0xff, 0x79, 0x12, 0x8a, 0x7b,
13642
-	0x23, 0x8b, 0x04, 0x54, 0xc6, 0x24, 0x2a, 0x43, 0x61, 0x44, 0x3c, 0xe2, 0x38, 0xd4, 0xb1, 0xfd,
13643
-	0xa1, 0x4a, 0x1b, 0xe2, 0x22, 0xf4, 0xe9, 0xdb, 0x4e, 0x63, 0x35, 0xc7, 0xe3, 0xec, 0x4f, 0xfe,
13644
-	0x75, 0x33, 0x11, 0x4e, 0xe8, 0x1e, 0xac, 0x1e, 0xc8, 0xde, 0xf6, 0x89, 0x29, 0x1c, 0x9b, 0x12,
13645
-	0x8e, 0xad, 0x2c, 0x72, 0x6c, 0xbc, 0x5b, 0x15, 0x35, 0x48, 0x43, 0x68, 0xe1, 0x95, 0x83, 0x78,
13646
-	0x11, 0xdd, 0x83, 0xe5, 0x21, 0x73, 0xed, 0x80, 0x79, 0x6f, 0xf6, 0x42, 0x88, 0x44, 0xb7, 0xe0,
13647
-	0x12, 0x77, 0x6e, 0xd8, 0x1f, 0x51, 0x2d, 0x4e, 0xac, 0x24, 0x5e, 0x1b, 0x92, 0xe7, 0xaa, 0x41,
13648
-	0xcc, 0xc5, 0xfa, 0xf7, 0x61, 0x65, 0xa6, 0x03, 0xfc, 0x14, 0xef, 0x18, 0x7b, 0xdd, 0x86, 0xb6,
13649
-	0x84, 0x8a, 0x90, 0xab, 0xb5, 0x5b, 0xbd, 0x66, 0x6b, 0x8f, 0xd3, 0x90, 0x22, 0xe4, 0x70, 0x7b,
13650
-	0x67, 0xa7, 0x6a, 0xd4, 0x9e, 0x68, 0x49, 0xfd, 0x3f, 0xa3, 0xd9, 0x55, 0x3c, 0xa4, 0x3a, 0xcb,
13651
-	0x43, 0x6e, 0xbf, 0x7e, 0xdc, 0x8a, 0x89, 0x4c, 0x0b, 0x11, 0x1f, 0xf9, 0x14, 0x40, 0x38, 0x91,
13652
-	0x5a, 0x7d, 0x12, 0x28, 0x27, 0x94, 0x5e, 0x19, 0x70, 0x2f, 0xcc, 0x24, 0x71, 0x5e, 0xa1, 0x8d,
13653
-	0x00, 0xfd, 0x00, 0x8a, 0x26, 0x1b, 0x8e, 0x1c, 0xaa, 0x94, 0x53, 0x6f, 0x54, 0x2e, 0x44, 0x78,
13654
-	0x23, 0x88, 0x33, 0xa1, 0xf4, 0x2c, 0x57, 0xfb, 0x83, 0x04, 0x14, 0x62, 0x5d, 0x9d, 0x25, 0x3f,
13655
-	0x45, 0xc8, 0xed, 0x75, 0xea, 0x46, 0xaf, 0xd9, 0x7a, 0xac, 0x25, 0x10, 0x40, 0x56, 0x4c, 0x5d,
13656
-	0x5d, 0x4b, 0x72, 0xd2, 0x56, 0x6b, 0xef, 0x76, 0x76, 0x1a, 0x82, 0xfe, 0xa0, 0x2b, 0xa0, 0x85,
13657
-	0x93, 0xd7, 0xef, 0xf6, 0x0c, 0xcc, 0xa5, 0x69, 0x74, 0x19, 0xd6, 0x22, 0xa9, 0xd2, 0xcc, 0xa0,
13658
-	0xab, 0x80, 0x22, 0xe1, 0xd4, 0x44, 0x56, 0xff, 0x5d, 0x58, 0xab, 0x31, 0x37, 0x20, 0xb6, 0x1b,
13659
-	0x11, 0xda, 0x2d, 0x3e, 0x68, 0x25, 0xea, 0xdb, 0x96, 0xdc, 0x5f, 0xab, 0x6b, 0xe7, 0x2f, 0x37,
13660
-	0x0b, 0x11, 0xb4, 0x59, 0xe7, 0x23, 0x0d, 0x0b, 0x16, 0x5f, 0x4b, 0x23, 0xdb, 0x12, 0x93, 0x9b,
13661
-	0xa9, 0x2e, 0x9f, 0xbf, 0xdc, 0x4c, 0x75, 0x9a, 0x75, 0xcc, 0x65, 0xe8, 0x1d, 0xc8, 0xd3, 0xe7,
13662
-	0x76, 0xd0, 0x37, 0xf9, 0x7e, 0xca, 0x27, 0x30, 0x83, 0x73, 0x5c, 0x50, 0xe3, 0xdb, 0x67, 0x15,
13663
-	0xa0, 0xc3, 0xbc, 0x40, 0xb5, 0xfc, 0x3d, 0xc8, 0x8c, 0x98, 0x27, 0xb2, 0x49, 0x7e, 0xd8, 0x2c,
13664
-	0xa4, 0x67, 0x1c, 0x2e, 0x63, 0x1c, 0x4b, 0xb0, 0xfe, 0xf7, 0x49, 0x80, 0x1e, 0xf1, 0x8f, 0x94,
13665
-	0x91, 0xfb, 0x90, 0x8f, 0x6e, 0x05, 0x54, 0x5a, 0x7a, 0xa1, 0xb7, 0x23, 0x30, 0xba, 0x17, 0x06,
13666
-	0x9b, 0xa4, 0xea, 0x0b, 0xd3, 0x8a, 0xb0, 0xa1, 0x45, 0x6c, 0x77, 0x96, 0x8f, 0xf3, 0xe3, 0x89,
13667
-	0x7a, 0x9e, 0xf2, 0x3c, 0xff, 0x44, 0x35, 0xb1, 0x45, 0xcb, 0x49, 0x53, 0x64, 0xef, 0xfd, 0x45,
13668
-	0x8d, 0xcc, 0x79, 0x64, 0x7b, 0x09, 0x4f, 0xf5, 0xd0, 0x43, 0x28, 0xf0, 0x71, 0xf7, 0x7d, 0x51,
13669
-	0xa7, 0x78, 0xde, 0x6b, 0xa7, 0x4a, 0x5a, 0xc0, 0x30, 0x8a, 0xbe, 0xab, 0x1a, 0xac, 0x7a, 0x63,
13670
-	0x97, 0x0f, 0x5b, 0xd9, 0xd0, 0x6d, 0xf8, 0x76, 0x8b, 0x06, 0x27, 0xcc, 0x3b, 0x32, 0x82, 0x80,
13671
-	0x98, 0x87, 0x3c, 0xb9, 0x57, 0xdb, 0xdb, 0x94, 0xe4, 0x26, 0x66, 0x48, 0xee, 0x3a, 0x2c, 0x13,
13672
-	0xc7, 0x26, 0x3e, 0x95, 0xcc, 0x20, 0x8f, 0xc3, 0x22, 0xa7, 0xe2, 0x9c, 0xd8, 0x53, 0xdf, 0xa7,
13673
-	0x32, 0x1d, 0xcd, 0xe3, 0xa9, 0x40, 0xff, 0xa7, 0x24, 0x40, 0xb3, 0x63, 0xec, 0x2a, 0xf3, 0x75,
13674
-	0xc8, 0x1e, 0x90, 0xa1, 0xed, 0x4c, 0x2e, 0x5a, 0xe0, 0x53, 0x7c, 0xc5, 0x90, 0x86, 0x1e, 0x09,
13675
-	0x1d, 0xac, 0x74, 0x05, 0x43, 0x1f, 0xef, 0xbb, 0x34, 0x88, 0x18, 0xba, 0x28, 0x71, 0x3a, 0xe0,
13676
-	0x11, 0x37, 0xf2, 0x8c, 0x2c, 0xf0, 0xae, 0x0f, 0x48, 0x40, 0x4f, 0xc8, 0x24, 0x5c, 0x95, 0xaa,
13677
-	0x88, 0xb6, 0x39, 0x73, 0xf7, 0xa9, 0x77, 0x4c, 0xad, 0xf5, 0x8c, 0x08, 0xc1, 0x37, 0xf5, 0x07,
13678
-	0x2b, 0xb8, 0x24, 0x3a, 0x91, 0x76, 0xe9, 0x81, 0x38, 0x9d, 0xa7, 0x55, 0xdf, 0x28, 0x99, 0xbe,
13679
-	0x03, 0x2b, 0x33, 0xe3, 0x7c, 0x25, 0x35, 0x6a, 0x76, 0x9e, 0x7e, 0x4f, 0x4b, 0xab, 0xaf, 0xef,
13680
-	0x6b, 0x59, 0xfd, 0xaf, 0x52, 0x72, 0x1d, 0xa9, 0x59, 0x5d, 0x7c, 0x3d, 0x95, 0x13, 0xd1, 0x6f,
13681
-	0x32, 0x47, 0xc5, 0xf7, 0x87, 0x17, 0x2f, 0x2f, 0x4e, 0xb5, 0x05, 0x1c, 0x47, 0x8a, 0x68, 0x13,
13682
-	0x0a, 0xd2, 0xff, 0x7d, 0x1e, 0x4f, 0x62, 0x5a, 0x57, 0x30, 0x48, 0x11, 0xd7, 0x44, 0x37, 0x60,
13683
-	0x75, 0x34, 0xde, 0x77, 0x6c, 0xff, 0x90, 0x5a, 0x12, 0x93, 0x16, 0x98, 0x95, 0x48, 0x2a, 0x60,
13684
-	0xbb, 0x50, 0x54, 0x82, 0xbe, 0xa0, 0x59, 0x19, 0xd1, 0xa1, 0x5b, 0x6f, 0xea, 0x90, 0x54, 0x11,
13685
-	0xec, 0xab, 0x30, 0x9a, 0x16, 0xf4, 0x3a, 0xe4, 0xc2, 0xce, 0xa2, 0x75, 0x48, 0xf5, 0x6a, 0x1d,
13686
-	0x6d, 0xa9, 0xb4, 0x76, 0x7a, 0x56, 0x2e, 0x84, 0xe2, 0x5e, 0xad, 0xc3, 0x6b, 0xf6, 0xea, 0x1d,
13687
-	0x2d, 0x31, 0x5b, 0xb3, 0x57, 0xef, 0x94, 0xd2, 0xfc, 0xb8, 0xd7, 0x0f, 0xa0, 0x10, 0x6b, 0x01,
13688
-	0xbd, 0x0f, 0xcb, 0xcd, 0xd6, 0x63, 0xdc, 0xe8, 0x76, 0xb5, 0xa5, 0xd2, 0xd5, 0xd3, 0xb3, 0x32,
13689
-	0x8a, 0xd5, 0x36, 0xdd, 0x01, 0xf7, 0x0f, 0x7a, 0x17, 0xd2, 0xdb, 0xed, 0x6e, 0x2f, 0xe4, 0x75,
13690
-	0x31, 0xc4, 0x36, 0xf3, 0x83, 0xd2, 0x65, 0xc5, 0x23, 0xe2, 0x86, 0xf5, 0x3f, 0x4d, 0x40, 0x56,
13691
-	0xd2, 0xdb, 0x85, 0x8e, 0x32, 0x60, 0x39, 0x4c, 0xba, 0x24, 0xe7, 0xfe, 0xf0, 0xf5, 0xfc, 0xb8,
13692
-	0xa2, 0xe8, 0xac, 0x0c, 0xbf, 0x50, 0xaf, 0xf4, 0x19, 0x14, 0xe3, 0x15, 0xdf, 0x28, 0xf8, 0x7e,
13693
-	0x07, 0x0a, 0x3c, 0xbe, 0x43, 0x9e, 0xbc, 0x05, 0x59, 0x49, 0xc1, 0xa3, 0xad, 0xf4, 0xf5, 0x64,
13694
-	0x5d, 0x21, 0xd1, 0x7d, 0x58, 0x96, 0x04, 0x3f, 0xbc, 0x8e, 0xda, 0xb8, 0x78, 0x15, 0xe1, 0x10,
13695
-	0xae, 0x3f, 0x84, 0x74, 0x87, 0x52, 0x8f, 0xcf, 0xbd, 0xcb, 0x2c, 0x3a, 0x3d, 0x7d, 0x54, 0x6e,
13696
-	0x62, 0xd1, 0x66, 0x9d, 0xe7, 0x26, 0x16, 0x6d, 0x5a, 0xd1, 0x6d, 0x42, 0x32, 0x76, 0x9b, 0xd0,
13697
-	0x83, 0xe2, 0x33, 0x6a, 0x0f, 0x0e, 0x03, 0x6a, 0x09, 0x43, 0xb7, 0x21, 0x3d, 0xa2, 0x51, 0xe7,
13698
-	0xd7, 0x17, 0x06, 0x18, 0xa5, 0x1e, 0x16, 0x28, 0xbe, 0x8f, 0x9c, 0x08, 0x6d, 0x75, 0x09, 0xaa,
13699
-	0x4a, 0xfa, 0x3f, 0x26, 0x61, 0xb5, 0xe9, 0xfb, 0x63, 0xe2, 0x9a, 0x21, 0x31, 0xf9, 0xe1, 0x2c,
13700
-	0x31, 0xb9, 0xb9, 0x70, 0x84, 0x33, 0x2a, 0xb3, 0x97, 0x24, 0xea, 0x70, 0x48, 0x46, 0x87, 0x83,
13701
-	0xfe, 0x1f, 0x89, 0xf0, 0x26, 0xe4, 0x46, 0x6c, 0xb9, 0x97, 0xd6, 0x4f, 0xcf, 0xca, 0x57, 0xe2,
13702
-	0x96, 0xe8, 0x9e, 0x7b, 0xe4, 0xb2, 0x13, 0x17, 0xbd, 0x07, 0x19, 0xdc, 0x68, 0x35, 0x9e, 0x69,
13703
-	0x09, 0x19, 0x9e, 0x33, 0x20, 0x4c, 0x5d, 0x7a, 0xc2, 0x2d, 0x75, 0x1a, 0xad, 0x3a, 0x27, 0x12,
13704
-	0xc9, 0x05, 0x96, 0x3a, 0xd4, 0xb5, 0x6c, 0x77, 0x80, 0xde, 0x87, 0x6c, 0xb3, 0xdb, 0xdd, 0x13,
13705
-	0xb9, 0xea, 0xb7, 0x4f, 0xcf, 0xca, 0x97, 0x67, 0x50, 0xbc, 0x40, 0x2d, 0x0e, 0xe2, 0x8c, 0x9a,
13706
-	0x53, 0x8c, 0x05, 0x20, 0x4e, 0xf7, 0x24, 0x08, 0xb7, 0x7b, 0x3c, 0x91, 0xce, 0x2c, 0x00, 0x61,
13707
-	0xc6, 0xff, 0xaa, 0xe5, 0xf6, 0xf3, 0x24, 0x68, 0x86, 0x69, 0xd2, 0x51, 0xc0, 0xeb, 0x55, 0x12,
13708
-	0xd3, 0x83, 0xdc, 0x88, 0x7f, 0xd9, 0x34, 0x24, 0x01, 0xf7, 0x17, 0x5e, 0xa3, 0xcf, 0xe9, 0x55,
13709
-	0x30, 0x73, 0xa8, 0x61, 0x0d, 0x6d, 0xdf, 0xe7, 0xc9, 0xba, 0x90, 0xe1, 0xc8, 0x52, 0xe9, 0xbf,
13710
-	0x12, 0x70, 0x79, 0x01, 0x02, 0xdd, 0x81, 0xb4, 0xc7, 0x9c, 0xd0, 0x87, 0xd7, 0x5f, 0x77, 0xc9,
13711
-	0xc5, 0x55, 0xb1, 0x40, 0xa2, 0x0d, 0x00, 0x32, 0x0e, 0x18, 0x11, 0xed, 0x0b, 0xef, 0xe5, 0x70,
13712
-	0x4c, 0x82, 0x9e, 0x41, 0xd6, 0xa7, 0xa6, 0x47, 0x43, 0xaa, 0xf8, 0xf0, 0xff, 0xdb, 0xfb, 0x4a,
13713
-	0x57, 0x98, 0xc1, 0xca, 0x5c, 0xa9, 0x02, 0x59, 0x29, 0xe1, 0x61, 0x6f, 0x91, 0x80, 0x88, 0x4e,
13714
-	0x17, 0xb1, 0xf8, 0xe6, 0xd1, 0x44, 0x9c, 0x41, 0x18, 0x4d, 0xc4, 0x19, 0xe8, 0x7f, 0x96, 0x04,
13715
-	0x68, 0x3c, 0x0f, 0xa8, 0xe7, 0x12, 0xa7, 0x66, 0xa0, 0x46, 0x6c, 0xf7, 0x97, 0xa3, 0xfd, 0x68,
13716
-	0xe1, 0xd5, 0x67, 0xa4, 0x51, 0xa9, 0x19, 0x0b, 0xf6, 0xff, 0x6b, 0x90, 0x1a, 0x7b, 0x8e, 0xba,
13717
-	0x46, 0x17, 0x34, 0x6f, 0x0f, 0xef, 0x60, 0x2e, 0x43, 0x8d, 0xe9, 0xb6, 0x95, 0x7a, 0xfd, 0xfb,
13718
-	0x47, 0xac, 0x81, 0x5f, 0xff, 0xd6, 0x75, 0x1b, 0x60, 0xda, 0x6b, 0xb4, 0x01, 0x99, 0xda, 0xa3,
13719
-	0x6e, 0x77, 0x47, 0x5b, 0x92, 0x7b, 0xf3, 0xb4, 0x4a, 0x88, 0xf5, 0x9f, 0x24, 0x20, 0x57, 0x33,
13720
-	0xd4, 0x89, 0x59, 0x03, 0x4d, 0x6c, 0x38, 0x26, 0xf5, 0x82, 0x3e, 0x7d, 0x3e, 0xb2, 0xbd, 0x89,
13721
-	0xda, 0x33, 0x2e, 0x48, 0x8d, 0x56, 0xb9, 0x4a, 0x8d, 0x7a, 0x41, 0x43, 0x28, 0x20, 0x0c, 0x45,
13722
-	0xaa, 0xc6, 0xd7, 0x37, 0x49, 0xb8, 0x7d, 0x6f, 0x5c, 0x3c, 0x0f, 0x92, 0x58, 0x4f, 0xcb, 0x3e,
13723
-	0x2e, 0x84, 0x46, 0x6a, 0xc4, 0xd7, 0x9f, 0xc2, 0xe5, 0xb6, 0x67, 0x1e, 0x52, 0x3f, 0x90, 0x8d,
13724
-	0xaa, 0xfe, 0x3e, 0x84, 0xeb, 0x01, 0xf1, 0x8f, 0xfa, 0x87, 0xb6, 0x1f, 0x30, 0x6f, 0xd2, 0xf7,
13725
-	0x68, 0x40, 0x5d, 0x5e, 0xdf, 0x17, 0x4f, 0x2c, 0xea, 0x42, 0xe3, 0x1a, 0xc7, 0x6c, 0x4b, 0x08,
13726
-	0x0e, 0x11, 0x3b, 0x1c, 0xa0, 0x37, 0xa1, 0xc8, 0xa9, 0x6c, 0x9d, 0x1e, 0x90, 0xb1, 0x13, 0xf8,
13727
-	0x3c, 0x49, 0x72, 0xd8, 0xa0, 0xff, 0xd6, 0x7b, 0x7d, 0xde, 0x61, 0x03, 0xf9, 0xa9, 0xff, 0x18,
13728
-	0xb4, 0xba, 0xed, 0x8f, 0x48, 0x60, 0x1e, 0x86, 0x37, 0x35, 0xa8, 0x0e, 0xda, 0x21, 0x25, 0x5e,
13729
-	0xb0, 0x4f, 0x49, 0xd0, 0x1f, 0x51, 0xcf, 0x66, 0xd6, 0x9b, 0xe7, 0x73, 0x2d, 0x52, 0xe9, 0x08,
13730
-	0x0d, 0xfd, 0xbf, 0x13, 0x00, 0x98, 0x1c, 0x84, 0xb4, 0xe6, 0xbb, 0x70, 0xc9, 0x77, 0xc9, 0xc8,
13731
-	0x3f, 0x64, 0x41, 0xdf, 0x76, 0x03, 0xea, 0x1d, 0x13, 0x47, 0x25, 0xdc, 0x5a, 0x58, 0xd1, 0x54,
13732
-	0x72, 0x74, 0x1b, 0xd0, 0x11, 0xa5, 0xa3, 0x3e, 0x73, 0xac, 0x7e, 0x58, 0x29, 0x1f, 0x80, 0xd2,
13733
-	0x58, 0xe3, 0x35, 0x6d, 0xc7, 0xea, 0x86, 0x72, 0x54, 0x85, 0x0d, 0x3e, 0x7c, 0xea, 0x06, 0x9e,
13734
-	0x4d, 0xfd, 0xfe, 0x01, 0xf3, 0xfa, 0xbe, 0xc3, 0x4e, 0xfa, 0x07, 0xcc, 0x71, 0xd8, 0x09, 0xf5,
13735
-	0xc2, 0xbb, 0x8c, 0x92, 0xc3, 0x06, 0x0d, 0x09, 0x7a, 0xc4, 0xbc, 0xae, 0xc3, 0x4e, 0x1e, 0x85,
13736
-	0x08, 0xce, 0x7d, 0xa6, 0x63, 0x0e, 0x6c, 0xf3, 0x28, 0xe4, 0x3e, 0x91, 0xb4, 0x67, 0x9b, 0x47,
13737
-	0xe8, 0x7d, 0x58, 0xa1, 0x0e, 0x15, 0x69, 0xb1, 0x44, 0x65, 0x04, 0xaa, 0x18, 0x0a, 0x39, 0x48,
13738
-	0xff, 0x1c, 0xb4, 0x86, 0x6b, 0x7a, 0x93, 0x51, 0xcc, 0xe7, 0xb7, 0x01, 0xf1, 0x9d, 0xa6, 0xef,
13739
-	0x30, 0xf3, 0xa8, 0x3f, 0x24, 0x2e, 0x19, 0xf0, 0x7e, 0xc9, 0x47, 0x07, 0x8d, 0xd7, 0xec, 0x30,
13740
-	0xf3, 0x68, 0x57, 0xc9, 0xf5, 0x4f, 0x01, 0xba, 0x23, 0x8f, 0x12, 0xab, 0xcd, 0x8f, 0x64, 0x3e,
13741
-	0x75, 0xa2, 0xd4, 0xb7, 0xd4, 0xbb, 0x06, 0xf3, 0xd4, 0xa2, 0xd2, 0x64, 0x45, 0x3d, 0x92, 0xeb,
13742
-	0xbf, 0x01, 0x97, 0x3b, 0x0e, 0x31, 0xc5, 0x1b, 0x5f, 0x27, 0xba, 0x45, 0x47, 0xf7, 0x21, 0x2b,
13743
-	0xa1, 0xca, 0x93, 0x0b, 0x03, 0x7b, 0xda, 0xe6, 0xf6, 0x12, 0x56, 0xf8, 0x6a, 0x11, 0x60, 0x6a,
13744
-	0x47, 0x7f, 0x0e, 0xf9, 0xc8, 0x3c, 0x2a, 0x03, 0xcf, 0x23, 0x79, 0x74, 0xdb, 0xae, 0x4a, 0xfc,
13745
-	0xf2, 0x38, 0x2e, 0x42, 0x4d, 0x28, 0x8c, 0x22, 0xe5, 0x0b, 0x39, 0xd1, 0x82, 0x4e, 0xe3, 0xb8,
13746
-	0xae, 0xfe, 0x43, 0x80, 0x1f, 0x31, 0xdb, 0xed, 0xb1, 0x23, 0xea, 0x8a, 0x87, 0x1b, 0x9e, 0xf2,
13747
-	0xd0, 0x70, 0x22, 0x54, 0x49, 0x64, 0x74, 0x72, 0x16, 0xa3, 0xf7, 0x0b, 0x59, 0xd4, 0xbf, 0x4e,
13748
-	0x40, 0x16, 0x33, 0x16, 0xd4, 0x0c, 0x54, 0x86, 0xac, 0x49, 0xfa, 0xe1, 0xd6, 0x54, 0xac, 0xe6,
13749
-	0xcf, 0x5f, 0x6e, 0x66, 0x6a, 0xc6, 0x13, 0x3a, 0xc1, 0x19, 0x93, 0x3c, 0xa1, 0x13, 0xce, 0x61,
13750
-	0x4c, 0x22, 0x36, 0x14, 0x61, 0xa6, 0x28, 0x39, 0x4c, 0xcd, 0xe0, 0x1b, 0x06, 0xce, 0x9a, 0x84,
13751
-	0xff, 0x47, 0x77, 0xa0, 0xa8, 0x40, 0xfd, 0x43, 0xe2, 0x1f, 0xca, 0x44, 0xa5, 0xba, 0x7a, 0xfe,
13752
-	0x72, 0x13, 0x24, 0x72, 0x9b, 0xf8, 0x87, 0x18, 0x24, 0x9a, 0x7f, 0xa3, 0x06, 0x14, 0xbe, 0x64,
13753
-	0xb6, 0xdb, 0x0f, 0xc4, 0x20, 0xd4, 0xfd, 0xcd, 0x42, 0x57, 0x4c, 0x87, 0xaa, 0x1e, 0xfa, 0xe0,
13754
-	0xcb, 0x48, 0xa2, 0xff, 0x73, 0x02, 0x0a, 0xdc, 0xa6, 0x7d, 0x60, 0x9b, 0x9c, 0x73, 0x7c, 0xf3,
13755
-	0xa3, 0xf0, 0x1a, 0xa4, 0x4c, 0xdf, 0x53, 0x63, 0x13, 0x67, 0x41, 0xad, 0x8b, 0x31, 0x97, 0xa1,
13756
-	0xcf, 0x21, 0xab, 0xb2, 0x53, 0x79, 0x0a, 0xea, 0x6f, 0x66, 0x47, 0xaa, 0x8b, 0x4a, 0x4f, 0x84,
13757
-	0xc5, 0xb4, 0x77, 0x62, 0x94, 0x45, 0x1c, 0x17, 0xa1, 0xab, 0x90, 0x34, 0x5d, 0xb1, 0x76, 0xd4,
13758
-	0x83, 0x6e, 0xad, 0x85, 0x93, 0xa6, 0xab, 0xff, 0x43, 0x02, 0x56, 0xa6, 0x4b, 0x87, 0x3b, 0xe2,
13759
-	0x3a, 0xe4, 0xfd, 0xf1, 0xbe, 0x3f, 0xf1, 0x03, 0x3a, 0x0c, 0xdf, 0x86, 0x22, 0x01, 0x6a, 0x42,
13760
-	0x9e, 0x38, 0x03, 0xe6, 0xd9, 0xc1, 0xe1, 0x50, 0x25, 0x46, 0x8b, 0x4f, 0xae, 0xb8, 0xcd, 0x8a,
13761
-	0x11, 0xaa, 0xe0, 0xa9, 0x76, 0x78, 0x56, 0xa5, 0x44, 0x67, 0xc5, 0x59, 0xf5, 0x1e, 0x14, 0x1d,
13762
-	0x32, 0x14, 0xe9, 0x3a, 0xcf, 0xb7, 0xc5, 0x38, 0xd2, 0xb8, 0xa0, 0x64, 0x3d, 0x7b, 0x48, 0x75,
13763
-	0x1d, 0xf2, 0x91, 0x31, 0xb4, 0x06, 0x05, 0xa3, 0xd1, 0xed, 0xdf, 0xdd, 0xba, 0xdf, 0x7f, 0x5c,
13764
-	0xdb, 0xd5, 0x96, 0x14, 0x55, 0xfa, 0xdb, 0x04, 0xac, 0xa8, 0x85, 0xad, 0xe8, 0xe7, 0xfb, 0xb0,
13765
-	0xec, 0x91, 0x83, 0x20, 0x24, 0xc8, 0x69, 0x19, 0x5c, 0x7c, 0xaf, 0xe4, 0x04, 0x99, 0x57, 0x2d,
13766
-	0x26, 0xc8, 0xb1, 0xd7, 0xca, 0xd4, 0x85, 0xaf, 0x95, 0xe9, 0x5f, 0xcb, 0x6b, 0xa5, 0xfe, 0xd7,
13767
-	0x49, 0x58, 0x53, 0x4c, 0x26, 0xda, 0x47, 0x3e, 0x82, 0xbc, 0x24, 0x35, 0x53, 0x7a, 0x2f, 0x1e,
13768
-	0xc8, 0x24, 0xae, 0x59, 0xc7, 0x39, 0x59, 0xdd, 0xb4, 0x78, 0xbe, 0xa9, 0xa0, 0xb1, 0xb7, 0x77,
13769
-	0x90, 0xa2, 0x16, 0x4f, 0x96, 0xea, 0x90, 0x3e, 0xb0, 0x1d, 0xaa, 0xe2, 0x6c, 0xe1, 0xb5, 0xe8,
13770
-	0x5c, 0xf3, 0xe2, 0x02, 0xbf, 0x27, 0x32, 0xd6, 0xed, 0x25, 0x2c, 0xb4, 0x4b, 0xbf, 0x07, 0x30,
13771
-	0x95, 0x2e, 0x4c, 0xca, 0x38, 0xf1, 0x51, 0xf7, 0x5b, 0x21, 0xf1, 0x69, 0xd6, 0x31, 0x97, 0xf1,
13772
-	0xaa, 0x81, 0x6d, 0xa9, 0x95, 0x2b, 0xaa, 0x1e, 0xf3, 0xaa, 0x81, 0x6d, 0x45, 0xaf, 0x08, 0xe9,
13773
-	0x37, 0xbc, 0x22, 0x54, 0x73, 0xe1, 0x2d, 0x8b, 0xbe, 0x03, 0x57, 0xab, 0x0e, 0x31, 0x8f, 0x1c,
13774
-	0xdb, 0x0f, 0xa8, 0x15, 0x5f, 0xa1, 0x5b, 0x90, 0x9d, 0x21, 0x26, 0x17, 0x5d, 0x6a, 0x29, 0xa4,
13775
-	0xfe, 0x97, 0x09, 0x28, 0x6e, 0x53, 0xe2, 0x04, 0x87, 0xd3, 0x9b, 0x81, 0x80, 0xfa, 0x81, 0xda,
13776
-	0x67, 0xc5, 0x37, 0xfa, 0x04, 0x72, 0xd1, 0x69, 0xfa, 0xc6, 0x9b, 0xfe, 0x08, 0x8a, 0xee, 0xc1,
13777
-	0x32, 0x8f, 0x69, 0x36, 0x0e, 0xb9, 0xee, 0x45, 0x97, 0xc8, 0x0a, 0xc9, 0xf7, 0x56, 0x8f, 0x8a,
13778
-	0xe3, 0x53, 0x4c, 0x4a, 0x06, 0x87, 0x45, 0xfd, 0x7f, 0x13, 0x70, 0x65, 0x97, 0x4c, 0xf6, 0xa9,
13779
-	0x5a, 0x68, 0xd4, 0xc2, 0xd4, 0x64, 0x9e, 0x85, 0x3a, 0xf1, 0x05, 0x7a, 0xc1, 0xbb, 0xc6, 0x22,
13780
-	0xe5, 0xc5, 0xeb, 0x34, 0x64, 0xd0, 0xc9, 0x18, 0x83, 0xbe, 0x02, 0x19, 0x97, 0xb9, 0x26, 0x55,
13781
-	0xab, 0x57, 0x16, 0x74, 0x3b, 0xbe, 0x38, 0x4b, 0xd1, 0x93, 0x83, 0x78, 0x30, 0x68, 0xb1, 0x20,
13782
-	0x6a, 0x0d, 0x7d, 0x0e, 0xa5, 0x6e, 0xa3, 0x86, 0x1b, 0xbd, 0x6a, 0xfb, 0xc7, 0xfd, 0xae, 0xb1,
13783
-	0xd3, 0x35, 0xb6, 0xee, 0xf4, 0x3b, 0xed, 0x9d, 0x2f, 0xee, 0xde, 0xbb, 0xf3, 0x89, 0x96, 0x28,
13784
-	0x95, 0x4f, 0xcf, 0xca, 0xd7, 0x5b, 0x46, 0x6d, 0x47, 0x46, 0xe3, 0x3e, 0x7b, 0xde, 0x25, 0x8e,
13785
-	0x4f, 0xb6, 0xee, 0x74, 0x98, 0x33, 0xe1, 0x98, 0x5b, 0xbf, 0x4c, 0x41, 0x3e, 0xba, 0x5c, 0xe4,
13786
-	0x41, 0xc5, 0x33, 0x3b, 0xd5, 0x54, 0x24, 0x6f, 0xd1, 0x13, 0xf4, 0xde, 0x34, 0xa7, 0xfb, 0x5c,
13787
-	0xbe, 0x6c, 0x44, 0xd5, 0x61, 0x3e, 0xf7, 0x01, 0xe4, 0x8c, 0x6e, 0xb7, 0xf9, 0xb8, 0xd5, 0xa8,
13788
-	0x6b, 0x5f, 0x25, 0x4a, 0xdf, 0x3a, 0x3d, 0x2b, 0x5f, 0x8a, 0x40, 0x86, 0xef, 0xdb, 0x03, 0x97,
13789
-	0x5a, 0x02, 0x55, 0xab, 0x35, 0x3a, 0xbd, 0x46, 0x5d, 0x7b, 0x91, 0x9c, 0x47, 0x89, 0x1c, 0x45,
13790
-	0xbc, 0x4f, 0xe6, 0x3b, 0xb8, 0xd1, 0x31, 0x30, 0x6f, 0xf0, 0xab, 0xa4, 0x4c, 0x35, 0xa7, 0x2d,
13791
-	0x7a, 0x74, 0x44, 0x3c, 0xde, 0xe6, 0x46, 0xf8, 0x4e, 0xff, 0x22, 0x25, 0xdf, 0xb0, 0xa6, 0x37,
13792
-	0xa5, 0x94, 0x58, 0x13, 0xde, 0x9a, 0xb8, 0xa2, 0x16, 0x66, 0x52, 0x73, 0xad, 0x75, 0x03, 0xe2,
13793
-	0x05, 0xdc, 0x8a, 0x0e, 0xcb, 0x78, 0xaf, 0xd5, 0xe2, 0xa0, 0x17, 0xe9, 0xb9, 0xd1, 0xe1, 0xb1,
13794
-	0xeb, 0x72, 0xcc, 0x0d, 0xc8, 0x85, 0x37, 0xd8, 0xda, 0x57, 0xe9, 0xb9, 0x0e, 0xd5, 0xc2, 0xeb,
13795
-	0x77, 0xd1, 0xe0, 0xf6, 0x5e, 0x4f, 0xfc, 0x8c, 0xe0, 0x45, 0x66, 0xbe, 0xc1, 0xc3, 0x71, 0x60,
13796
-	0xf1, 0x24, 0xba, 0x1c, 0x65, 0xb5, 0x5f, 0x65, 0x64, 0x9e, 0x10, 0x61, 0x54, 0x4a, 0xfb, 0x01,
13797
-	0xe4, 0x70, 0xe3, 0x47, 0xf2, 0x17, 0x07, 0x2f, 0xb2, 0x73, 0x76, 0x30, 0xfd, 0x92, 0x9a, 0xaa,
13798
-	0xb5, 0x36, 0xee, 0x6c, 0x1b, 0x62, 0xca, 0xe7, 0x51, 0x6d, 0x6f, 0x74, 0x48, 0x5c, 0x6a, 0x4d,
13799
-	0x1f, 0xf2, 0xa2, 0xaa, 0x5b, 0xbf, 0x09, 0xb9, 0xf0, 0x60, 0x45, 0x1b, 0x90, 0x7d, 0xd6, 0xc6,
13800
-	0x4f, 0x1a, 0x58, 0x5b, 0x92, 0x73, 0x18, 0xd6, 0x3c, 0x93, 0xcc, 0xa4, 0x0c, 0xcb, 0xbb, 0x46,
13801
-	0xcb, 0x78, 0xdc, 0xc0, 0xe1, 0x85, 0x53, 0x08, 0x50, 0xa7, 0x43, 0x49, 0x53, 0x0d, 0x44, 0x36,
13802
-	0xab, 0xeb, 0x5f, 0xff, 0x62, 0x63, 0xe9, 0x67, 0xbf, 0xd8, 0x58, 0x7a, 0x71, 0xbe, 0x91, 0xf8,
13803
-	0xfa, 0x7c, 0x23, 0xf1, 0xd3, 0xf3, 0x8d, 0xc4, 0xbf, 0x9d, 0x6f, 0x24, 0xf6, 0xb3, 0x62, 0x9d,
13804
-	0xde, 0xfb, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc8, 0xe3, 0x0e, 0xba, 0x76, 0x27, 0x00, 0x00,
13550
+	// 4248 bytes of a gzipped FileDescriptorProto
13551
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x5a, 0x4d, 0x6c, 0x24, 0x49,
13552
+	0x56, 0x76, 0xfd, 0xba, 0xea, 0x55, 0xd9, 0x9d, 0x1d, 0xdd, 0xdb, 0xeb, 0xae, 0xed, 0xb1, 0x6b,
13553
+	0x72, 0xa6, 0x77, 0x7e, 0x76, 0x54, 0xd3, 0xed, 0xde, 0x59, 0xf5, 0xcc, 0xb0, 0x33, 0x93, 0xf5,
13554
+	0xe3, 0x76, 0x6d, 0xdb, 0x55, 0xa5, 0xa8, 0x72, 0xf7, 0xce, 0x01, 0x52, 0xe1, 0xcc, 0x70, 0x39,
13555
+	0xc7, 0x59, 0x19, 0x45, 0x66, 0x96, 0xdd, 0x05, 0x42, 0xb4, 0x38, 0x00, 0xf2, 0x05, 0x8e, 0x48,
13556
+	0xc8, 0xa7, 0xe5, 0xc4, 0x81, 0x0b, 0x07, 0x24, 0x2e, 0xcc, 0x81, 0xc3, 0xdc, 0x58, 0x40, 0x42,
13557
+	0x2b, 0x90, 0x1a, 0xc6, 0x48, 0xdc, 0x10, 0x5c, 0x56, 0x5c, 0x40, 0x42, 0xf1, 0x93, 0x59, 0x69,
13558
+	0x77, 0xd9, 0xee, 0x61, 0xb8, 0xd8, 0x19, 0x2f, 0xbe, 0xf7, 0xe2, 0x45, 0xc4, 0x8b, 0x88, 0xef,
13559
+	0x45, 0x14, 0x94, 0xc2, 0xe9, 0x98, 0x06, 0xb5, 0xb1, 0xcf, 0x42, 0x86, 0x90, 0xcd, 0xac, 0x03,
13560
+	0xea, 0xd7, 0x82, 0x23, 0xe2, 0x8f, 0x0e, 0x9c, 0xb0, 0x76, 0x78, 0xbf, 0xb2, 0x36, 0x64, 0x6c,
13561
+	0xe8, 0xd2, 0xf7, 0x05, 0x62, 0x77, 0xb2, 0xf7, 0x7e, 0xe8, 0x8c, 0x68, 0x10, 0x92, 0xd1, 0x58,
13562
+	0x2a, 0x55, 0x56, 0xcf, 0x03, 0xec, 0x89, 0x4f, 0x42, 0x87, 0x79, 0xaa, 0xfe, 0xe6, 0x90, 0x0d,
13563
+	0x99, 0xf8, 0x7c, 0x9f, 0x7f, 0x49, 0xa9, 0xbe, 0x06, 0x8b, 0x4f, 0xa8, 0x1f, 0x38, 0xcc, 0x43,
13564
+	0x37, 0x21, 0xe7, 0x78, 0x36, 0x7d, 0xb6, 0x92, 0xaa, 0xa6, 0xde, 0xce, 0x62, 0x59, 0xd0, 0xef,
13565
+	0x01, 0xb4, 0xf9, 0x47, 0xcb, 0x0b, 0xfd, 0x29, 0xd2, 0x20, 0x73, 0x40, 0xa7, 0x02, 0x51, 0xc4,
13566
+	0xfc, 0x93, 0x4b, 0x0e, 0x89, 0xbb, 0x92, 0x96, 0x92, 0x43, 0xe2, 0xea, 0x5f, 0xa7, 0xa0, 0x64,
13567
+	0x78, 0x1e, 0x0b, 0x45, 0xeb, 0x01, 0x42, 0x90, 0xf5, 0xc8, 0x88, 0x2a, 0x25, 0xf1, 0x8d, 0x1a,
13568
+	0x90, 0x77, 0xc9, 0x2e, 0x75, 0x83, 0x95, 0x74, 0x35, 0xf3, 0x76, 0x69, 0xfd, 0x07, 0xb5, 0x97,
13569
+	0xbb, 0x5c, 0x4b, 0x18, 0xa9, 0x6d, 0x09, 0xb4, 0x70, 0x02, 0x2b, 0x55, 0xf4, 0x09, 0x2c, 0x3a,
13570
+	0x9e, 0xed, 0x58, 0x34, 0x58, 0xc9, 0x0a, 0x2b, 0xab, 0xf3, 0xac, 0xcc, 0xbc, 0xaf, 0x67, 0xbf,
13571
+	0x7a, 0xb1, 0xb6, 0x80, 0x23, 0xa5, 0xca, 0x87, 0x50, 0x4a, 0x98, 0x9d, 0xd3, 0xb7, 0x9b, 0x90,
13572
+	0x3b, 0x24, 0xee, 0x84, 0xaa, 0xde, 0xc9, 0xc2, 0x47, 0xe9, 0x87, 0x29, 0xfd, 0x73, 0x28, 0x62,
13573
+	0x1a, 0xb0, 0x89, 0x6f, 0xd1, 0x00, 0xbd, 0x03, 0x45, 0x8f, 0x78, 0xcc, 0xb4, 0xc6, 0x93, 0x40,
13574
+	0xa8, 0x67, 0xea, 0xe5, 0xd3, 0x17, 0x6b, 0x85, 0x0e, 0xf1, 0x58, 0xa3, 0xb7, 0x13, 0xe0, 0x02,
13575
+	0xaf, 0x6e, 0x8c, 0x27, 0x01, 0x7a, 0x1d, 0xca, 0x23, 0x3a, 0x62, 0xfe, 0xd4, 0xdc, 0x9d, 0x86,
13576
+	0x34, 0x10, 0x86, 0x33, 0xb8, 0x24, 0x65, 0x75, 0x2e, 0xd2, 0xff, 0x30, 0x05, 0x37, 0x23, 0xdb,
13577
+	0x98, 0xfe, 0xfa, 0xc4, 0xf1, 0xe9, 0x88, 0x7a, 0x61, 0x80, 0x3e, 0x80, 0xbc, 0xeb, 0x8c, 0x9c,
13578
+	0x50, 0xb6, 0x51, 0x5a, 0x7f, 0x6d, 0x5e, 0x6f, 0x63, 0xaf, 0xb0, 0x02, 0x23, 0x03, 0xca, 0x3e,
13579
+	0x0d, 0xa8, 0x7f, 0x28, 0x47, 0x52, 0x34, 0x79, 0xa5, 0xf2, 0x19, 0x15, 0x7d, 0x03, 0x0a, 0x3d,
13580
+	0x97, 0x84, 0x7b, 0xcc, 0x1f, 0x21, 0x1d, 0xca, 0xc4, 0xb7, 0xf6, 0x9d, 0x90, 0x5a, 0xe1, 0xc4,
13581
+	0x8f, 0x66, 0xf5, 0x8c, 0x0c, 0xdd, 0x82, 0x34, 0x93, 0x0d, 0x15, 0xeb, 0xf9, 0xd3, 0x17, 0x6b,
13582
+	0xe9, 0x6e, 0x1f, 0xa7, 0x59, 0xa0, 0x7f, 0x0c, 0xd7, 0x7b, 0xee, 0x64, 0xe8, 0x78, 0x4d, 0x1a,
13583
+	0x58, 0xbe, 0x33, 0xe6, 0xd6, 0x79, 0x78, 0xf0, 0xd8, 0x8f, 0xc2, 0x83, 0x7f, 0xc7, 0x21, 0x93,
13584
+	0x9e, 0x85, 0x8c, 0xfe, 0x7b, 0x69, 0xb8, 0xde, 0xf2, 0x86, 0x8e, 0x47, 0x93, 0xda, 0x77, 0x61,
13585
+	0x99, 0x0a, 0xa1, 0x79, 0x28, 0xc3, 0x58, 0xd9, 0x59, 0x92, 0xd2, 0x28, 0xb6, 0xdb, 0xe7, 0xe2,
13586
+	0xed, 0xfe, 0xbc, 0xee, 0xbf, 0x64, 0x7d, 0x6e, 0xd4, 0xb5, 0x60, 0x71, 0x2c, 0x3a, 0x11, 0xac,
13587
+	0x64, 0x84, 0xad, 0xbb, 0xf3, 0x6c, 0xbd, 0xd4, 0xcf, 0x28, 0xf8, 0x94, 0xee, 0xb7, 0x09, 0xbe,
13588
+	0x7f, 0x4d, 0xc1, 0xb5, 0x0e, 0xb3, 0xcf, 0x8c, 0x43, 0x05, 0x0a, 0xfb, 0x2c, 0x08, 0x13, 0x0b,
13589
+	0x2d, 0x2e, 0xa3, 0x87, 0x50, 0x18, 0xab, 0xe9, 0x53, 0xb3, 0x7f, 0x67, 0xbe, 0xcb, 0x12, 0x83,
13590
+	0x63, 0x34, 0xfa, 0x18, 0x8a, 0x7e, 0x14, 0x13, 0x2b, 0x99, 0x57, 0x09, 0x9c, 0x19, 0x1e, 0xfd,
13591
+	0x18, 0xf2, 0x72, 0x12, 0x56, 0xb2, 0x42, 0xf3, 0xee, 0x2b, 0x8d, 0x39, 0x56, 0x4a, 0xfa, 0x2f,
13592
+	0x52, 0xa0, 0x61, 0xb2, 0x17, 0x6e, 0xd3, 0xd1, 0x2e, 0xf5, 0xfb, 0x21, 0x09, 0x27, 0x01, 0xba,
13593
+	0x05, 0x79, 0x97, 0x12, 0x9b, 0xfa, 0xa2, 0x93, 0x05, 0xac, 0x4a, 0x68, 0x87, 0x07, 0x39, 0xb1,
13594
+	0xf6, 0xc9, 0xae, 0xe3, 0x3a, 0xe1, 0x54, 0x74, 0x73, 0x79, 0xfe, 0x2c, 0x9f, 0xb7, 0x59, 0xc3,
13595
+	0x09, 0x45, 0x7c, 0xc6, 0x0c, 0x5a, 0x81, 0xc5, 0x11, 0x0d, 0x02, 0x32, 0xa4, 0xa2, 0xf7, 0x45,
13596
+	0x1c, 0x15, 0xf5, 0x8f, 0xa1, 0x9c, 0xd4, 0x43, 0x25, 0x58, 0xdc, 0xe9, 0x3c, 0xee, 0x74, 0x9f,
13597
+	0x76, 0xb4, 0x05, 0x74, 0x0d, 0x4a, 0x3b, 0x1d, 0xdc, 0x32, 0x1a, 0x9b, 0x46, 0x7d, 0xab, 0xa5,
13598
+	0xa5, 0xd0, 0x12, 0x14, 0x67, 0xc5, 0xb4, 0xfe, 0xe7, 0x29, 0x00, 0x3e, 0x81, 0xaa, 0x53, 0x1f,
13599
+	0x41, 0x2e, 0x08, 0x49, 0x28, 0x27, 0x6e, 0x79, 0xfd, 0xcd, 0x79, 0x5e, 0xcf, 0xe0, 0x35, 0xfe,
13600
+	0x8f, 0x62, 0xa9, 0x92, 0xf4, 0x30, 0x7d, 0xc6, 0x43, 0xbe, 0x86, 0x88, 0x6d, 0xfb, 0xca, 0x71,
13601
+	0xf1, 0xad, 0x7f, 0x0c, 0x39, 0xa1, 0x7d, 0xd6, 0xdd, 0x02, 0x64, 0x9b, 0xfc, 0x2b, 0x85, 0x8a,
13602
+	0x90, 0xc3, 0x2d, 0xa3, 0xf9, 0xb9, 0x96, 0x46, 0x1a, 0x94, 0x9b, 0xed, 0x7e, 0xa3, 0xdb, 0xe9,
13603
+	0xb4, 0x1a, 0x83, 0x56, 0x53, 0xcb, 0xe8, 0x77, 0x21, 0xd7, 0x1e, 0x71, 0xcb, 0x77, 0x78, 0x54,
13604
+	0xec, 0x51, 0x9f, 0x7a, 0x56, 0x14, 0x6c, 0x33, 0x81, 0xfe, 0xf3, 0x22, 0xe4, 0xb6, 0xd9, 0xc4,
13605
+	0x0b, 0xd1, 0x7a, 0x62, 0x65, 0x2f, 0xcf, 0xdf, 0x9c, 0x05, 0xb0, 0x36, 0x98, 0x8e, 0xa9, 0x5a,
13606
+	0xf9, 0xb7, 0x20, 0x2f, 0xe3, 0x47, 0x75, 0x47, 0x95, 0xb8, 0x3c, 0x24, 0xfe, 0x90, 0x86, 0xaa,
13607
+	0x3f, 0xaa, 0x84, 0xde, 0x86, 0x82, 0x4f, 0x89, 0xcd, 0x3c, 0x77, 0x2a, 0xc2, 0xac, 0x20, 0xb7,
13608
+	0x5e, 0x4c, 0x89, 0xdd, 0xf5, 0xdc, 0x29, 0x8e, 0x6b, 0xd1, 0x26, 0x94, 0x77, 0x1d, 0xcf, 0x36,
13609
+	0xd9, 0x58, 0xee, 0x83, 0xb9, 0x8b, 0x83, 0x52, 0x7a, 0x55, 0x77, 0x3c, 0xbb, 0x2b, 0xc1, 0xb8,
13610
+	0xb4, 0x3b, 0x2b, 0xa0, 0x0e, 0x2c, 0x1f, 0x32, 0x77, 0x32, 0xa2, 0xb1, 0xad, 0xbc, 0xb0, 0xf5,
13611
+	0xd6, 0xc5, 0xb6, 0x9e, 0x08, 0x7c, 0x64, 0x6d, 0xe9, 0x30, 0x59, 0x44, 0x8f, 0x61, 0x29, 0x1c,
13612
+	0x8d, 0xf7, 0x82, 0xd8, 0xdc, 0xa2, 0x30, 0xf7, 0xfd, 0x4b, 0x06, 0x8c, 0xc3, 0x23, 0x6b, 0xe5,
13613
+	0x30, 0x51, 0xaa, 0xfc, 0x4e, 0x06, 0x4a, 0x09, 0xcf, 0x51, 0x1f, 0x4a, 0x63, 0x9f, 0x8d, 0xc9,
13614
+	0x50, 0xec, 0xe5, 0x6a, 0x2e, 0xee, 0xbf, 0x52, 0xaf, 0x6b, 0xbd, 0x99, 0x22, 0x4e, 0x5a, 0xd1,
13615
+	0x4f, 0xd2, 0x50, 0x4a, 0x54, 0xa2, 0x77, 0xa1, 0x80, 0x7b, 0xb8, 0xfd, 0xc4, 0x18, 0xb4, 0xb4,
13616
+	0x85, 0xca, 0x9d, 0xe3, 0x93, 0xea, 0x8a, 0xb0, 0x96, 0x34, 0xd0, 0xf3, 0x9d, 0x43, 0x1e, 0x7a,
13617
+	0x6f, 0xc3, 0x62, 0x04, 0x4d, 0x55, 0xbe, 0x77, 0x7c, 0x52, 0xfd, 0xee, 0x79, 0x68, 0x02, 0x89,
13618
+	0xfb, 0x9b, 0x06, 0x6e, 0x35, 0xb5, 0xf4, 0x7c, 0x24, 0xee, 0xef, 0x13, 0x9f, 0xda, 0xe8, 0xfb,
13619
+	0x90, 0x57, 0xc0, 0x4c, 0xa5, 0x72, 0x7c, 0x52, 0xbd, 0x75, 0x1e, 0x38, 0xc3, 0xe1, 0xfe, 0x96,
13620
+	0xf1, 0xa4, 0xa5, 0x65, 0xe7, 0xe3, 0x70, 0xdf, 0x25, 0x87, 0x14, 0xbd, 0x09, 0x39, 0x09, 0xcb,
13621
+	0x55, 0x6e, 0x1f, 0x9f, 0x54, 0xbf, 0xf3, 0x92, 0x39, 0x8e, 0xaa, 0xac, 0xfc, 0xfe, 0xcf, 0x56,
13622
+	0x17, 0xfe, 0xf2, 0x4f, 0x56, 0xb5, 0xf3, 0xd5, 0x95, 0xff, 0x4e, 0xc1, 0xd2, 0x99, 0x29, 0x47,
13623
+	0x3a, 0xe4, 0x3d, 0x66, 0xb1, 0xb1, 0xdc, 0xe2, 0x0b, 0x75, 0x38, 0x7d, 0xb1, 0x96, 0xef, 0xb0,
13624
+	0x06, 0x1b, 0x4f, 0xb1, 0xaa, 0x41, 0x8f, 0xcf, 0x1d, 0x52, 0x0f, 0x5e, 0x31, 0x9e, 0xe6, 0x1e,
13625
+	0x53, 0x9f, 0xc2, 0x92, 0xed, 0x3b, 0x87, 0xd4, 0x37, 0x2d, 0xe6, 0xed, 0x39, 0x43, 0xb5, 0x7d,
13626
+	0x57, 0xe6, 0xd9, 0x6c, 0x0a, 0x20, 0x2e, 0x4b, 0x85, 0x86, 0xc0, 0x7f, 0x8b, 0x03, 0xaa, 0xf2,
13627
+	0x04, 0xca, 0xc9, 0x08, 0x45, 0xaf, 0x01, 0x04, 0xce, 0x6f, 0x50, 0xc5, 0x79, 0x04, 0x43, 0xc2,
13628
+	0x45, 0x2e, 0x11, 0x8c, 0x07, 0xbd, 0x05, 0xd9, 0x11, 0xb3, 0xa5, 0x9d, 0xa5, 0xfa, 0x0d, 0x7e,
13629
+	0x4e, 0xfe, 0xe3, 0x8b, 0xb5, 0x12, 0x0b, 0x6a, 0x1b, 0x8e, 0x4b, 0xb7, 0x99, 0x4d, 0xb1, 0x00,
13630
+	0xe8, 0x87, 0x90, 0xe5, 0x5b, 0x05, 0xfa, 0x1e, 0x64, 0xeb, 0xed, 0x4e, 0x53, 0x5b, 0xa8, 0x5c,
13631
+	0x3f, 0x3e, 0xa9, 0x2e, 0x89, 0x21, 0xe1, 0x15, 0x3c, 0x76, 0xd1, 0x1a, 0xe4, 0x9f, 0x74, 0xb7,
13632
+	0x76, 0xb6, 0x79, 0x78, 0xdd, 0x38, 0x3e, 0xa9, 0x5e, 0x8b, 0xab, 0xe5, 0xa0, 0xa1, 0xd7, 0x20,
13633
+	0x37, 0xd8, 0xee, 0x6d, 0xf4, 0xb5, 0x74, 0x05, 0x1d, 0x9f, 0x54, 0x97, 0xe3, 0x7a, 0xe1, 0x73,
13634
+	0xe5, 0xba, 0x9a, 0xd5, 0x62, 0x2c, 0xd7, 0x7f, 0x99, 0x86, 0x25, 0xcc, 0xc9, 0xb6, 0x1f, 0xf6,
13635
+	0x98, 0xeb, 0x58, 0x53, 0xd4, 0x83, 0xa2, 0xc5, 0x3c, 0xdb, 0x49, 0xac, 0xa9, 0xf5, 0x0b, 0x0e,
13636
+	0xc6, 0x99, 0x56, 0x54, 0x6a, 0x44, 0x9a, 0x78, 0x66, 0x04, 0xbd, 0x0f, 0x39, 0x9b, 0xba, 0x64,
13637
+	0xaa, 0x4e, 0xe8, 0xdb, 0x35, 0x49, 0xe7, 0x6b, 0x11, 0x9d, 0xaf, 0x35, 0x15, 0x9d, 0xc7, 0x12,
13638
+	0x27, 0xa8, 0x24, 0x79, 0x66, 0x92, 0x30, 0xa4, 0xa3, 0x71, 0x28, 0x8f, 0xe7, 0x2c, 0x2e, 0x8d,
13639
+	0xc8, 0x33, 0x43, 0x89, 0xd0, 0x7d, 0xc8, 0x1f, 0x39, 0x9e, 0xcd, 0x8e, 0xd4, 0x09, 0x7c, 0x89,
13640
+	0x51, 0x05, 0xd4, 0x8f, 0xf9, 0xa9, 0x7b, 0xce, 0x4d, 0x3e, 0xde, 0x9d, 0x6e, 0xa7, 0x15, 0x8d,
13641
+	0xb7, 0xaa, 0xef, 0x7a, 0x1d, 0xe6, 0xf1, 0xb5, 0x02, 0xdd, 0x8e, 0xb9, 0x61, 0xb4, 0xb7, 0x76,
13642
+	0x30, 0x1f, 0xf3, 0x9b, 0xc7, 0x27, 0x55, 0x2d, 0x86, 0x6c, 0x10, 0xc7, 0xe5, 0x94, 0xf0, 0x36,
13643
+	0x64, 0x8c, 0xce, 0xe7, 0x5a, 0xba, 0xa2, 0x1d, 0x9f, 0x54, 0xcb, 0x71, 0xb5, 0xe1, 0x4d, 0x67,
13644
+	0xcb, 0xe8, 0x7c, 0xbb, 0xfa, 0xdf, 0x64, 0xa0, 0xbc, 0x33, 0xb6, 0x49, 0x48, 0x65, 0x4c, 0xa2,
13645
+	0x2a, 0x94, 0xc6, 0xc4, 0x27, 0xae, 0x4b, 0x5d, 0x27, 0x18, 0xa9, 0x44, 0x25, 0x29, 0x42, 0x1f,
13646
+	0xbe, 0xea, 0x30, 0xd6, 0x0b, 0x3c, 0xce, 0xfe, 0xe8, 0x9f, 0xd7, 0x52, 0xd1, 0x80, 0xee, 0xc0,
13647
+	0xf2, 0x9e, 0xf4, 0xd6, 0x24, 0x96, 0x98, 0xd8, 0x8c, 0x98, 0xd8, 0xda, 0xbc, 0x89, 0x4d, 0xba,
13648
+	0x55, 0x53, 0x9d, 0x34, 0x84, 0x16, 0x5e, 0xda, 0x4b, 0x16, 0xd1, 0x03, 0x58, 0x1c, 0x31, 0xcf,
13649
+	0x09, 0x99, 0x7f, 0xf5, 0x2c, 0x44, 0x48, 0xf4, 0x2e, 0x5c, 0xe7, 0x93, 0x1b, 0xf9, 0x23, 0xaa,
13650
+	0xc5, 0x89, 0x95, 0xc6, 0xd7, 0x46, 0xe4, 0x99, 0x6a, 0x10, 0x73, 0x31, 0xaa, 0x43, 0x8e, 0xf9,
13651
+	0x9c, 0x12, 0xe5, 0x85, 0xbb, 0xef, 0x5d, 0xe9, 0xae, 0x2c, 0x74, 0xb9, 0x0e, 0x96, 0xaa, 0xfa,
13652
+	0x8f, 0x60, 0xe9, 0x4c, 0x27, 0x38, 0x13, 0xe8, 0x19, 0x3b, 0xfd, 0x96, 0xb6, 0x80, 0xca, 0x50,
13653
+	0x68, 0x74, 0x3b, 0x83, 0x76, 0x67, 0x87, 0x53, 0x99, 0x32, 0x14, 0x70, 0x77, 0x6b, 0xab, 0x6e,
13654
+	0x34, 0x1e, 0x6b, 0x69, 0xbd, 0x06, 0xa5, 0x84, 0x35, 0xb4, 0x0c, 0xd0, 0x1f, 0x74, 0x7b, 0xe6,
13655
+	0x46, 0x1b, 0xf7, 0x07, 0x92, 0x08, 0xf5, 0x07, 0x06, 0x1e, 0x28, 0x41, 0x4a, 0xff, 0x8f, 0x74,
13656
+	0x34, 0xa3, 0x8a, 0xfb, 0xd4, 0xcf, 0x72, 0x9f, 0x4b, 0x9c, 0x57, 0xec, 0x67, 0x56, 0x88, 0x39,
13657
+	0xd0, 0x87, 0x00, 0x22, 0x70, 0xa8, 0x6d, 0x92, 0x50, 0x4d, 0x7c, 0xe5, 0xa5, 0x41, 0x1e, 0x44,
13658
+	0xf9, 0x32, 0x2e, 0x2a, 0xb4, 0x11, 0xa2, 0x1f, 0x43, 0xd9, 0x62, 0xa3, 0xb1, 0x4b, 0x95, 0x72,
13659
+	0xe6, 0x4a, 0xe5, 0x52, 0x8c, 0x37, 0xc2, 0x24, 0xfb, 0xca, 0x9e, 0xe5, 0x87, 0xbf, 0x9b, 0x8a,
13660
+	0x46, 0x66, 0x0e, 0xe1, 0x2a, 0x43, 0x61, 0xa7, 0xd7, 0x34, 0x06, 0xed, 0xce, 0x23, 0x2d, 0x85,
13661
+	0x00, 0xf2, 0x62, 0xa8, 0x9b, 0x5a, 0x9a, 0x13, 0xc5, 0x46, 0x77, 0xbb, 0xb7, 0xd5, 0x12, 0x94,
13662
+	0x0b, 0xdd, 0x04, 0x2d, 0x1a, 0x6c, 0x53, 0x0c, 0x64, 0xab, 0xa9, 0x65, 0xd1, 0x0d, 0xb8, 0x16,
13663
+	0x4b, 0x95, 0x66, 0x0e, 0xdd, 0x02, 0x14, 0x0b, 0x67, 0x26, 0xf2, 0xfa, 0x6f, 0xc1, 0xb5, 0x06,
13664
+	0xf3, 0x42, 0xe2, 0x78, 0x31, 0x89, 0x5e, 0xe7, 0x9d, 0x56, 0x22, 0xd3, 0xb1, 0xe5, 0x9e, 0x5e,
13665
+	0xbf, 0x76, 0xfa, 0x62, 0xad, 0x14, 0x43, 0xdb, 0x4d, 0xde, 0xd3, 0xa8, 0x60, 0xf3, 0xf5, 0x3b,
13666
+	0x76, 0x6c, 0x31, 0xb8, 0xb9, 0xfa, 0xe2, 0xe9, 0x8b, 0xb5, 0x4c, 0xaf, 0xdd, 0xc4, 0x5c, 0x86,
13667
+	0xbe, 0x07, 0x45, 0xfa, 0xcc, 0x09, 0x4d, 0x8b, 0xef, 0xe1, 0x7c, 0x00, 0x73, 0xb8, 0xc0, 0x05,
13668
+	0x0d, 0xbe, 0x65, 0xd7, 0x01, 0x7a, 0xcc, 0x0f, 0x55, 0xcb, 0x3f, 0x84, 0xdc, 0x98, 0xf9, 0x22,
13669
+	0x83, 0xbd, 0x30, 0x5f, 0xe7, 0x70, 0x19, 0xa8, 0x58, 0x82, 0xf5, 0xbf, 0x4a, 0x03, 0x0c, 0x48,
13670
+	0x70, 0xa0, 0x8c, 0x3c, 0x84, 0x62, 0x7c, 0xf7, 0xa1, 0x52, 0xe1, 0x4b, 0x67, 0x3b, 0x06, 0xa3,
13671
+	0x07, 0x51, 0xb0, 0xc9, 0xf4, 0x60, 0x6e, 0x2a, 0x13, 0x35, 0x34, 0x8f, 0x61, 0x9f, 0xcd, 0x01,
13672
+	0xf8, 0x91, 0x48, 0x7d, 0x5f, 0xcd, 0x3c, 0xff, 0x44, 0x0d, 0x71, 0x2c, 0xc8, 0x41, 0x53, 0x04,
13673
+	0xf3, 0x8d, 0x79, 0x8d, 0x9c, 0x9b, 0x91, 0xcd, 0x05, 0x3c, 0xd3, 0x43, 0x9f, 0x42, 0x89, 0xf7,
13674
+	0xdb, 0x0c, 0x44, 0x9d, 0xe2, 0x96, 0x17, 0x0e, 0x95, 0xb4, 0x80, 0x61, 0x1c, 0x7f, 0xd7, 0x35,
13675
+	0x58, 0xf6, 0x27, 0x1e, 0xef, 0xb6, 0xb2, 0xa1, 0x3b, 0xf0, 0xdd, 0x0e, 0x0d, 0x8f, 0x98, 0x7f,
13676
+	0x60, 0x84, 0x21, 0xb1, 0xf6, 0x47, 0xd4, 0x53, 0x63, 0x9c, 0x20, 0xd6, 0xa9, 0x33, 0xc4, 0x7a,
13677
+	0x05, 0x16, 0x89, 0xeb, 0x90, 0x80, 0x4a, 0x36, 0x52, 0xc4, 0x51, 0x91, 0xd3, 0x7f, 0x9e, 0x4c,
13678
+	0xd0, 0x20, 0xa0, 0x32, 0x05, 0x2e, 0xe2, 0x99, 0x40, 0xff, 0xfb, 0x34, 0x40, 0xbb, 0x67, 0x6c,
13679
+	0x2b, 0xf3, 0x4d, 0xc8, 0xef, 0x91, 0x91, 0xe3, 0x4e, 0x2f, 0x5b, 0xe0, 0x33, 0x7c, 0xcd, 0x90,
13680
+	0x86, 0x36, 0x84, 0x0e, 0x56, 0xba, 0x22, 0x2b, 0x98, 0xec, 0x7a, 0x34, 0x8c, 0xb3, 0x02, 0x51,
13681
+	0xe2, 0x14, 0xc4, 0x27, 0x5e, 0x3c, 0x33, 0xb2, 0xc0, 0x5d, 0x1f, 0x92, 0x90, 0x1e, 0x91, 0x69,
13682
+	0xb4, 0x2a, 0x55, 0x11, 0x6d, 0xf2, 0x6c, 0x21, 0xa0, 0xfe, 0x21, 0xb5, 0x57, 0x72, 0x22, 0x04,
13683
+	0xaf, 0xf2, 0x07, 0x2b, 0xb8, 0x24, 0x57, 0xb1, 0x76, 0xe5, 0x63, 0xc1, 0x08, 0x66, 0x55, 0xdf,
13684
+	0x28, 0x81, 0xbf, 0x07, 0x4b, 0x67, 0xfa, 0xf9, 0x52, 0x3a, 0xd6, 0xee, 0x3d, 0xf9, 0xa1, 0x96,
13685
+	0x55, 0x5f, 0x3f, 0xd2, 0xf2, 0xfa, 0x9f, 0x66, 0xe4, 0x3a, 0x52, 0xa3, 0x3a, 0xff, 0x4a, 0xad,
13686
+	0x20, 0xa2, 0xdf, 0x62, 0xae, 0x8a, 0xef, 0xb7, 0x2e, 0x5f, 0x5e, 0x9c, 0xde, 0x0b, 0x38, 0x8e,
13687
+	0x15, 0xd1, 0x1a, 0x94, 0xe4, 0xfc, 0x9b, 0x3c, 0x9e, 0xc4, 0xb0, 0x2e, 0x61, 0x90, 0x22, 0xae,
13688
+	0x89, 0xee, 0xc2, 0xf2, 0x78, 0xb2, 0xeb, 0x3a, 0xc1, 0x3e, 0xb5, 0x25, 0x26, 0x2b, 0x30, 0x4b,
13689
+	0xb1, 0x54, 0xc0, 0xb6, 0xa1, 0xac, 0x04, 0xa6, 0xa0, 0x76, 0x39, 0xe1, 0xd0, 0xbb, 0x57, 0x39,
13690
+	0x24, 0x55, 0x04, 0xe3, 0x2b, 0x8d, 0x67, 0x05, 0xbd, 0x09, 0x85, 0xc8, 0x59, 0xb4, 0x02, 0x99,
13691
+	0x41, 0xa3, 0xa7, 0x2d, 0x54, 0xae, 0x1d, 0x9f, 0x54, 0x4b, 0x91, 0x78, 0xd0, 0xe8, 0xf1, 0x9a,
13692
+	0x9d, 0x66, 0x4f, 0x4b, 0x9d, 0xad, 0xd9, 0x69, 0xf6, 0x2a, 0x59, 0x4e, 0x31, 0xf4, 0x3d, 0x28,
13693
+	0x25, 0x5a, 0x40, 0x6f, 0xc0, 0x62, 0xbb, 0xf3, 0x08, 0xb7, 0xfa, 0x7d, 0x6d, 0xa1, 0x72, 0xeb,
13694
+	0xf8, 0xa4, 0x8a, 0x12, 0xb5, 0x6d, 0x6f, 0xc8, 0xe7, 0x07, 0xbd, 0x06, 0xd9, 0xcd, 0x2e, 0x3f,
13695
+	0xba, 0x24, 0x97, 0x4c, 0x20, 0x36, 0x59, 0x10, 0x56, 0x6e, 0x28, 0xee, 0x92, 0x34, 0xac, 0xff,
13696
+	0x71, 0x0a, 0xf2, 0x92, 0x52, 0xcf, 0x9d, 0x28, 0x03, 0x16, 0xa3, 0x44, 0x4f, 0xf2, 0xfc, 0xb7,
13697
+	0x2e, 0xe6, 0xe4, 0x35, 0x45, 0xa1, 0x65, 0xf8, 0x45, 0x7a, 0x95, 0x8f, 0xa0, 0x9c, 0xac, 0xf8,
13698
+	0x46, 0xc1, 0xf7, 0x9b, 0x50, 0xe2, 0xf1, 0x1d, 0x71, 0xf3, 0x75, 0xc8, 0x4b, 0xda, 0x1f, 0x6f,
13699
+	0xa5, 0x17, 0x27, 0x08, 0x0a, 0x89, 0x1e, 0xc2, 0xa2, 0x4c, 0x2a, 0xa2, 0x2b, 0xb0, 0xd5, 0xcb,
13700
+	0x57, 0x11, 0x8e, 0xe0, 0xfa, 0xa7, 0x90, 0xed, 0x51, 0xea, 0xf3, 0xb1, 0xf7, 0x98, 0x4d, 0x67,
13701
+	0xa7, 0x8f, 0xca, 0x87, 0x6c, 0xda, 0x6e, 0xf2, 0x7c, 0xc8, 0xa6, 0x6d, 0x3b, 0xbe, 0xc1, 0x48,
13702
+	0x27, 0x6e, 0x30, 0x06, 0x50, 0x7e, 0x4a, 0x9d, 0xe1, 0x7e, 0x48, 0x6d, 0x61, 0xe8, 0x3d, 0xc8,
13703
+	0x8e, 0x69, 0xec, 0xfc, 0xca, 0xdc, 0x00, 0xa3, 0xd4, 0xc7, 0x02, 0xc5, 0xf7, 0x91, 0x23, 0xa1,
13704
+	0xad, 0x2e, 0x5e, 0x55, 0x49, 0xff, 0xbb, 0x34, 0x2c, 0xb7, 0x83, 0x60, 0x42, 0x3c, 0x2b, 0x22,
13705
+	0x26, 0x9f, 0x9c, 0x25, 0x26, 0x6f, 0xcf, 0xed, 0xe1, 0x19, 0x95, 0xb3, 0x17, 0x33, 0xea, 0x70,
13706
+	0x48, 0xc7, 0x87, 0x83, 0xfe, 0xef, 0xa9, 0xe8, 0xf6, 0xe5, 0x6e, 0x62, 0xb9, 0x57, 0x56, 0x8e,
13707
+	0x4f, 0xaa, 0x37, 0x93, 0x96, 0xe8, 0x8e, 0x77, 0xe0, 0xb1, 0x23, 0x0f, 0xbd, 0x0e, 0x39, 0xdc,
13708
+	0xea, 0xb4, 0x9e, 0x6a, 0x29, 0x19, 0x9e, 0x67, 0x40, 0x98, 0x7a, 0xf4, 0x88, 0x5b, 0xea, 0xb5,
13709
+	0x3a, 0x4d, 0x4e, 0x24, 0xd2, 0x73, 0x2c, 0xf5, 0xa8, 0x67, 0x3b, 0xde, 0x10, 0xbd, 0x01, 0xf9,
13710
+	0x76, 0xbf, 0xbf, 0x23, 0xf2, 0xe3, 0xef, 0x1e, 0x9f, 0x54, 0x6f, 0x9c, 0x41, 0xf1, 0x02, 0xb5,
13711
+	0x39, 0x88, 0xb3, 0x78, 0x4e, 0x31, 0xe6, 0x80, 0x38, 0x3d, 0x94, 0x20, 0xdc, 0x1d, 0xf0, 0xe4,
13712
+	0x3d, 0x37, 0x07, 0x84, 0x19, 0xff, 0xab, 0x96, 0xdb, 0x3f, 0xa5, 0x41, 0x33, 0x2c, 0x8b, 0x8e,
13713
+	0x43, 0x5e, 0xaf, 0x12, 0xa7, 0x01, 0x14, 0xc6, 0xfc, 0xcb, 0xa1, 0x11, 0x09, 0x78, 0x38, 0xf7,
13714
+	0xea, 0xff, 0x9c, 0x5e, 0x0d, 0x33, 0x97, 0x1a, 0xf6, 0xc8, 0x09, 0x02, 0x87, 0x79, 0x52, 0x86,
13715
+	0x63, 0x4b, 0x95, 0xff, 0x4c, 0xc1, 0x8d, 0x39, 0x08, 0x74, 0x0f, 0xb2, 0x3e, 0x73, 0xa3, 0x39,
13716
+	0xbc, 0x73, 0xd1, 0xc5, 0x1a, 0x57, 0xc5, 0x02, 0x89, 0x56, 0x01, 0xc8, 0x24, 0x64, 0x44, 0xb4,
13717
+	0x2f, 0x66, 0xaf, 0x80, 0x13, 0x12, 0xf4, 0x14, 0xf2, 0x01, 0xb5, 0x7c, 0x1a, 0x51, 0xc5, 0x4f,
13718
+	0xff, 0xaf, 0xde, 0xd7, 0xfa, 0xc2, 0x0c, 0x56, 0xe6, 0x2a, 0x35, 0xc8, 0x4b, 0x09, 0x0f, 0x7b,
13719
+	0x9b, 0x84, 0x44, 0x38, 0x5d, 0xc6, 0xe2, 0x9b, 0x47, 0x13, 0x71, 0x87, 0x51, 0x34, 0x11, 0x77,
13720
+	0xa8, 0xff, 0x75, 0x1a, 0xa0, 0xf5, 0x2c, 0xa4, 0xbe, 0x47, 0xdc, 0x86, 0x81, 0x5a, 0x89, 0xdd,
13721
+	0x5f, 0xf6, 0xf6, 0x9d, 0xb9, 0xd7, 0xad, 0xb1, 0x46, 0xad, 0x61, 0xcc, 0xd9, 0xff, 0x6f, 0x43,
13722
+	0x66, 0xe2, 0xab, 0xd7, 0x1c, 0x49, 0xf3, 0x76, 0xf0, 0x16, 0xe6, 0x32, 0xd4, 0x9a, 0x6d, 0x5b,
13723
+	0x99, 0x8b, 0xdf, 0x6c, 0x12, 0x0d, 0xcc, 0xdd, 0xba, 0xf8, 0xca, 0xb7, 0x88, 0x69, 0x51, 0x75,
13724
+	0x72, 0x94, 0xe5, 0xca, 0x6f, 0x18, 0x0d, 0xea, 0x87, 0x38, 0x6f, 0x11, 0xfe, 0xff, 0x5b, 0xed,
13725
+	0x6f, 0xef, 0x01, 0xcc, 0xba, 0x86, 0x56, 0x21, 0xd7, 0xd8, 0xe8, 0xf7, 0xb7, 0xb4, 0x05, 0xb9,
13726
+	0x81, 0xcf, 0xaa, 0x84, 0x58, 0xff, 0x59, 0x0a, 0x0a, 0x0d, 0x43, 0x1d, 0xab, 0x0d, 0xd0, 0xc4,
13727
+	0xae, 0xc4, 0xbd, 0x33, 0xe9, 0xb3, 0xb1, 0xe3, 0x4f, 0xd5, 0xc6, 0x72, 0x49, 0xce, 0xb6, 0xcc,
13728
+	0x55, 0xb8, 0xd7, 0x2d, 0xa1, 0x80, 0x30, 0x94, 0xa9, 0x1a, 0x04, 0xd3, 0x22, 0xd1, 0x1e, 0xbf,
13729
+	0x7a, 0xf9, 0x60, 0x49, 0xf6, 0x3d, 0x2b, 0x07, 0xb8, 0x14, 0x19, 0x69, 0x90, 0x40, 0x7f, 0x02,
13730
+	0x37, 0xba, 0xbe, 0xb5, 0x4f, 0x83, 0x50, 0x36, 0xaa, 0xfc, 0xfd, 0x14, 0xee, 0x84, 0x24, 0x38,
13731
+	0x30, 0xf7, 0x9d, 0x20, 0x64, 0xfe, 0xd4, 0xf4, 0x69, 0x48, 0x3d, 0x5e, 0x6f, 0x8a, 0xb7, 0x1f,
13732
+	0x75, 0xd3, 0x72, 0x9b, 0x63, 0x36, 0x25, 0x04, 0x47, 0x88, 0x2d, 0x0e, 0xd0, 0xdb, 0x50, 0xe6,
13733
+	0x7c, 0xb7, 0x49, 0xf7, 0xc8, 0xc4, 0x0d, 0x03, 0x9e, 0x49, 0xb9, 0x6c, 0x68, 0xbe, 0xf2, 0x81,
13734
+	0x50, 0x74, 0xd9, 0x50, 0x7e, 0xea, 0x3f, 0x05, 0xad, 0xe9, 0x04, 0x63, 0x12, 0x5a, 0xfb, 0xd1,
13735
+	0x15, 0x12, 0x6a, 0x82, 0xb6, 0x4f, 0x89, 0x1f, 0xee, 0x52, 0x12, 0x9a, 0x63, 0xea, 0x3b, 0xcc,
13736
+	0xbe, 0x7a, 0x3c, 0xaf, 0xc5, 0x2a, 0x3d, 0xa1, 0xa1, 0xff, 0x57, 0x0a, 0x00, 0x93, 0xbd, 0x88,
13737
+	0xfb, 0xfc, 0x00, 0xae, 0x07, 0x1e, 0x19, 0x07, 0xfb, 0x2c, 0x34, 0x1d, 0x2f, 0xa4, 0xfe, 0x21,
13738
+	0x71, 0xd5, 0x4d, 0x80, 0x16, 0x55, 0xb4, 0x95, 0x1c, 0xbd, 0x07, 0xe8, 0x80, 0xd2, 0xb1, 0xc9,
13739
+	0x5c, 0xdb, 0x8c, 0x2a, 0xe5, 0xcb, 0x54, 0x16, 0x6b, 0xbc, 0xa6, 0xeb, 0xda, 0xfd, 0x48, 0x8e,
13740
+	0xea, 0xb0, 0xca, 0xbb, 0x4f, 0xbd, 0xd0, 0x77, 0x68, 0x60, 0xee, 0x31, 0xdf, 0x0c, 0x5c, 0x76,
13741
+	0x64, 0xee, 0x31, 0xd7, 0x65, 0x47, 0xd4, 0x8f, 0x2e, 0x59, 0x2a, 0x2e, 0x1b, 0xb6, 0x24, 0x68,
13742
+	0x83, 0xf9, 0x7d, 0x97, 0x1d, 0x6d, 0x44, 0x08, 0x4e, 0x90, 0x66, 0x7d, 0x0e, 0x1d, 0xeb, 0x20,
13743
+	0x22, 0x48, 0xb1, 0x74, 0xe0, 0x58, 0x07, 0xe8, 0x0d, 0x58, 0xa2, 0x2e, 0x15, 0xb9, 0xb6, 0x44,
13744
+	0xe5, 0x04, 0xaa, 0x1c, 0x09, 0x39, 0x48, 0xff, 0x0c, 0xb4, 0x96, 0x67, 0xf9, 0xd3, 0x71, 0x62,
13745
+	0xce, 0xdf, 0x03, 0xc4, 0xb7, 0x23, 0xd3, 0x65, 0xd6, 0x81, 0x39, 0x22, 0x1e, 0x19, 0x72, 0xbf,
13746
+	0xe4, 0x6b, 0x88, 0xc6, 0x6b, 0xb6, 0x98, 0x75, 0xb0, 0xad, 0xe4, 0xfa, 0x87, 0x00, 0xfd, 0xb1,
13747
+	0x4f, 0x89, 0xdd, 0xe5, 0xe7, 0x36, 0x1f, 0x3a, 0x51, 0x32, 0x6d, 0xf5, 0xe0, 0xc2, 0x7c, 0xb5,
13748
+	0xa8, 0x34, 0x59, 0xd1, 0x8c, 0xe5, 0xfa, 0xaf, 0xc2, 0x8d, 0x9e, 0x4b, 0x2c, 0xf1, 0xf8, 0xd8,
13749
+	0x8b, 0xaf, 0xf7, 0xd1, 0x43, 0xc8, 0x4b, 0xa8, 0x9a, 0xc9, 0xb9, 0x81, 0x3d, 0x6b, 0x73, 0x73,
13750
+	0x01, 0x2b, 0x7c, 0xbd, 0x0c, 0x30, 0xb3, 0xa3, 0x3f, 0x83, 0x62, 0x6c, 0x1e, 0x55, 0x81, 0x27,
13751
+	0x9b, 0x3c, 0xba, 0x1d, 0x4f, 0x65, 0x87, 0x45, 0x9c, 0x14, 0xa1, 0x36, 0x94, 0xc6, 0xb1, 0xf2,
13752
+	0xa5, 0xc4, 0x69, 0x8e, 0xd3, 0x38, 0xa9, 0xab, 0x7f, 0x02, 0xf0, 0x13, 0xe6, 0x78, 0x03, 0x76,
13753
+	0x40, 0x3d, 0xf1, 0xa2, 0xc4, 0xf3, 0x22, 0x1a, 0x0d, 0x84, 0x2a, 0x89, 0xb4, 0x4f, 0x8e, 0x62,
13754
+	0xfc, 0xb0, 0x22, 0x8b, 0xfa, 0x1f, 0xa4, 0x21, 0x8f, 0x19, 0x0b, 0x1b, 0x06, 0xaa, 0x42, 0xde,
13755
+	0x22, 0x66, 0xb4, 0x35, 0x95, 0xeb, 0xc5, 0xd3, 0x17, 0x6b, 0xb9, 0x86, 0xf1, 0x98, 0x4e, 0x71,
13756
+	0xce, 0x22, 0x8f, 0xe9, 0x34, 0xb9, 0xdd, 0xa5, 0x2f, 0xda, 0xee, 0xd0, 0x3d, 0x28, 0x2b, 0x90,
13757
+	0xb9, 0x4f, 0x82, 0x7d, 0x99, 0xcd, 0xd4, 0x97, 0x4f, 0x5f, 0xac, 0x81, 0x44, 0x6e, 0x92, 0x60,
13758
+	0x1f, 0x83, 0x44, 0xf3, 0x6f, 0xd4, 0x82, 0xd2, 0x17, 0xcc, 0xf1, 0xcc, 0x50, 0x74, 0x42, 0x5d,
13759
+	0x2c, 0xcd, 0x9d, 0x8a, 0x59, 0x57, 0xd5, 0x0b, 0x24, 0x7c, 0x31, 0xeb, 0x7c, 0x0b, 0x96, 0x7c,
13760
+	0xc6, 0x42, 0xd3, 0x57, 0xef, 0xec, 0x2a, 0x67, 0xad, 0xce, 0xbd, 0xca, 0x64, 0x2c, 0xc4, 0x0a,
13761
+	0x87, 0xcb, 0x7e, 0xa2, 0xa4, 0xff, 0x43, 0x0a, 0x4a, 0xdc, 0x35, 0x67, 0xcf, 0xb1, 0x38, 0xbf,
13762
+	0xf9, 0xe6, 0xc7, 0xee, 0x6d, 0xc8, 0x58, 0x81, 0xaf, 0x86, 0x48, 0x9c, 0x3b, 0x8d, 0x3e, 0xc6,
13763
+	0x5c, 0x86, 0x3e, 0x83, 0xbc, 0xca, 0x84, 0xe5, 0x89, 0xab, 0x5f, 0xcd, 0xc4, 0x54, 0x4f, 0x95,
13764
+	0x9e, 0x88, 0xae, 0x99, 0x77, 0xf2, 0xd8, 0xc1, 0x49, 0x11, 0xba, 0x05, 0x69, 0x4b, 0x76, 0x5e,
13765
+	0x3d, 0x58, 0x37, 0x3a, 0x38, 0x6d, 0x79, 0xfa, 0xdf, 0xa6, 0x60, 0x69, 0xb6, 0x02, 0xf9, 0x7c,
13766
+	0xde, 0x81, 0x62, 0x30, 0xd9, 0x0d, 0xa6, 0x41, 0x48, 0x47, 0xd1, 0xdb, 0x57, 0x2c, 0x40, 0x6d,
13767
+	0x28, 0x12, 0x77, 0xc8, 0x7c, 0x27, 0xdc, 0x1f, 0xa9, 0x24, 0x6c, 0xfe, 0x29, 0x99, 0xb4, 0x59,
13768
+	0x33, 0x22, 0x15, 0x3c, 0xd3, 0x8e, 0x8e, 0xbc, 0x8c, 0x70, 0x56, 0x1c, 0x79, 0xaf, 0x43, 0xd9,
13769
+	0x25, 0x23, 0x71, 0x35, 0xc0, 0x73, 0x7b, 0xd1, 0x8f, 0x2c, 0x2e, 0x29, 0xd9, 0xc0, 0x19, 0x51,
13770
+	0x5d, 0x87, 0x62, 0x6c, 0x0c, 0x5d, 0x83, 0x92, 0xd1, 0xea, 0x9b, 0xf7, 0xd7, 0x1f, 0x9a, 0x8f,
13771
+	0x1a, 0xdb, 0xda, 0x82, 0xa2, 0x65, 0x7f, 0x91, 0x82, 0x25, 0xb5, 0x3f, 0x28, 0xaa, 0xfb, 0x06,
13772
+	0x2c, 0xfa, 0x64, 0x2f, 0x8c, 0xc8, 0x78, 0x56, 0xc6, 0x28, 0xdf, 0x72, 0x39, 0x19, 0xe7, 0x55,
13773
+	0xf3, 0xc9, 0x78, 0xe2, 0x35, 0x36, 0x73, 0xe9, 0x6b, 0x6c, 0xf6, 0xff, 0xe5, 0x35, 0x56, 0xff,
13774
+	0xb3, 0x34, 0x5c, 0x53, 0xac, 0x29, 0xde, 0x8e, 0xde, 0x81, 0xa2, 0x24, 0x50, 0xb3, 0x54, 0x42,
13775
+	0x3c, 0x00, 0x4a, 0x5c, 0xbb, 0x89, 0x0b, 0xb2, 0xba, 0x6d, 0xf3, 0xdc, 0x56, 0x41, 0x13, 0xbf,
13776
+	0x2d, 0x00, 0x29, 0xea, 0xf0, 0xc4, 0xac, 0x09, 0xd9, 0x3d, 0xc7, 0xa5, 0x2a, 0xce, 0xe6, 0x5e,
13777
+	0xfb, 0x9e, 0x6b, 0x5e, 0x3c, 0x50, 0x0c, 0x44, 0x76, 0xbc, 0xb9, 0x80, 0x85, 0x76, 0xe5, 0xb7,
13778
+	0x01, 0x66, 0xd2, 0xb9, 0x09, 0x20, 0x27, 0x59, 0xea, 0x2e, 0x2d, 0x22, 0x59, 0xed, 0x26, 0xe6,
13779
+	0x32, 0x5e, 0x35, 0x74, 0x6c, 0xb5, 0x01, 0x88, 0xaa, 0x47, 0xbc, 0x6a, 0xe8, 0xd8, 0xf1, 0x2b,
13780
+	0x49, 0xf6, 0x8a, 0x57, 0x92, 0x7a, 0x21, 0xba, 0xd1, 0xd1, 0xb7, 0xe0, 0x56, 0xdd, 0x25, 0xd6,
13781
+	0x81, 0xeb, 0x04, 0x21, 0xb5, 0x93, 0x2b, 0x74, 0x1d, 0xf2, 0x67, 0xf8, 0xcd, 0x65, 0x17, 0x68,
13782
+	0x0a, 0xa9, 0xff, 0x5b, 0x0a, 0xca, 0x9b, 0x94, 0xb8, 0xe1, 0xfe, 0xec, 0x16, 0x22, 0xa4, 0x41,
13783
+	0xa8, 0xb6, 0x6b, 0xf1, 0x8d, 0x3e, 0x80, 0x42, 0x7c, 0x28, 0x5f, 0xf9, 0x92, 0x11, 0x43, 0xd1,
13784
+	0x03, 0x58, 0xe4, 0x31, 0xcd, 0x26, 0x11, 0xaf, 0xbe, 0xec, 0x92, 0x5c, 0x21, 0xf9, 0x16, 0xed,
13785
+	0x53, 0x71, 0x0a, 0x8b, 0x41, 0xc9, 0xe1, 0xa8, 0x88, 0x7e, 0x05, 0xca, 0xe2, 0x8e, 0x37, 0x22,
13786
+	0x1d, 0xb9, 0xab, 0x6c, 0x96, 0xe4, 0x33, 0x8d, 0x24, 0x1c, 0xff, 0x93, 0x82, 0x9b, 0xdb, 0x64,
13787
+	0xba, 0x4b, 0xd5, 0x32, 0xa5, 0x36, 0xa6, 0x16, 0xf3, 0x6d, 0xd4, 0x4b, 0x2e, 0xef, 0x4b, 0x5e,
13788
+	0x7d, 0xe6, 0x29, 0xcf, 0x5f, 0xe5, 0x11, 0xd7, 0x4f, 0x27, 0xb8, 0xfe, 0x4d, 0xc8, 0x79, 0xcc,
13789
+	0xb3, 0xa8, 0x5a, 0xfb, 0xb2, 0xa0, 0x3b, 0xc9, 0xa5, 0x5d, 0x89, 0x1f, 0x64, 0xc4, 0x73, 0x4a,
13790
+	0x87, 0x85, 0x71, 0x6b, 0xe8, 0x33, 0xa8, 0xf4, 0x5b, 0x0d, 0xdc, 0x1a, 0xd4, 0xbb, 0x3f, 0x35,
13791
+	0xfb, 0xc6, 0x56, 0xdf, 0x58, 0xbf, 0x67, 0xf6, 0xba, 0x5b, 0x9f, 0xdf, 0x7f, 0x70, 0xef, 0x03,
13792
+	0x2d, 0x55, 0xa9, 0x1e, 0x9f, 0x54, 0xef, 0x74, 0x8c, 0xc6, 0x96, 0x8c, 0xe5, 0x5d, 0xf6, 0xac,
13793
+	0x4f, 0xdc, 0x80, 0xac, 0xdf, 0xeb, 0x31, 0x77, 0xca, 0x31, 0xfa, 0x49, 0x0a, 0xca, 0xc9, 0xdd,
13794
+	0x3e, 0x79, 0x88, 0xa5, 0x2e, 0x3c, 0xc4, 0x66, 0x67, 0x61, 0xfa, 0x82, 0xb3, 0x70, 0x03, 0x6e,
13795
+	0x5a, 0x3e, 0x0b, 0x02, 0x33, 0x70, 0x86, 0x1e, 0xb5, 0xcd, 0xc8, 0xa6, 0xe8, 0x67, 0xfd, 0x3b,
13796
+	0xa7, 0x2f, 0xd6, 0xae, 0x37, 0x78, 0x7d, 0x5f, 0x54, 0x2b, 0xf3, 0xd7, 0xad, 0x84, 0x48, 0xb4,
13797
+	0xf4, 0xee, 0x2f, 0x33, 0x50, 0x8c, 0xaf, 0x69, 0xf9, 0x92, 0xe1, 0x39, 0xb2, 0x1a, 0x8a, 0x58,
13798
+	0xde, 0xa1, 0x47, 0xe8, 0xf5, 0x59, 0x76, 0xfc, 0x99, 0x7c, 0x97, 0x8a, 0xab, 0xa3, 0xcc, 0xf8,
13799
+	0x4d, 0x28, 0x18, 0xfd, 0x7e, 0xfb, 0x51, 0xa7, 0xd5, 0xd4, 0xbe, 0x4c, 0x55, 0xbe, 0x73, 0x7c,
13800
+	0x52, 0xbd, 0x1e, 0x83, 0x8c, 0x40, 0x7a, 0x2a, 0x50, 0x8d, 0x46, 0xab, 0x37, 0x68, 0x35, 0xb5,
13801
+	0xe7, 0xe9, 0xf3, 0x28, 0x91, 0xed, 0x89, 0xd7, 0xe5, 0x62, 0x0f, 0xb7, 0x7a, 0x06, 0xe6, 0x0d,
13802
+	0x7e, 0x99, 0x96, 0x49, 0xfb, 0xac, 0x45, 0x9f, 0x8e, 0x89, 0xcf, 0xdb, 0x5c, 0x8d, 0x7e, 0x65,
13803
+	0xf1, 0x3c, 0x23, 0x5f, 0x20, 0x67, 0x77, 0xce, 0x94, 0xd8, 0x53, 0xde, 0x9a, 0xb8, 0xec, 0x17,
13804
+	0x66, 0x32, 0xe7, 0x5a, 0xeb, 0xf3, 0x40, 0xe5, 0x56, 0x74, 0x58, 0xc4, 0x3b, 0x9d, 0x0e, 0x07,
13805
+	0x3d, 0xcf, 0x9e, 0xeb, 0x1d, 0x9e, 0x78, 0x1e, 0xc7, 0xdc, 0x85, 0x42, 0xf4, 0x16, 0xa0, 0x7d,
13806
+	0x99, 0x3d, 0xe7, 0x50, 0x23, 0x7a, 0xc8, 0x10, 0x0d, 0x6e, 0xee, 0x0c, 0xc4, 0x8f, 0x40, 0x9e,
13807
+	0xe7, 0xce, 0x37, 0xb8, 0x3f, 0x09, 0x6d, 0x76, 0xe4, 0xf1, 0x09, 0x56, 0xf7, 0x03, 0x5f, 0xe6,
13808
+	0x64, 0x32, 0x15, 0x63, 0xd4, 0xe5, 0xc0, 0x9b, 0x50, 0xc0, 0xad, 0x9f, 0xc8, 0xdf, 0x8b, 0x3c,
13809
+	0xcf, 0x9f, 0xb3, 0x83, 0xe9, 0x17, 0xd4, 0x52, 0xad, 0x75, 0x71, 0x6f, 0xd3, 0x10, 0x43, 0x7e,
13810
+	0x1e, 0xd5, 0xf5, 0xc7, 0xfb, 0xc4, 0xa3, 0xf6, 0xec, 0x19, 0x36, 0xae, 0x7a, 0xf7, 0xd7, 0xa0,
13811
+	0x10, 0xd1, 0x06, 0xb4, 0x0a, 0xf9, 0xa7, 0x5d, 0xfc, 0xb8, 0x85, 0xb5, 0x05, 0x39, 0x86, 0x51,
13812
+	0xcd, 0x53, 0x49, 0xdf, 0xaa, 0xb0, 0xb8, 0x6d, 0x74, 0x8c, 0x47, 0x2d, 0x1c, 0x5d, 0xdd, 0x45,
13813
+	0x00, 0x75, 0xf6, 0x55, 0x34, 0xd5, 0x40, 0x6c, 0xb3, 0xbe, 0xf2, 0xd5, 0xd7, 0xab, 0x0b, 0xbf,
13814
+	0xf8, 0x7a, 0x75, 0xe1, 0xf9, 0xe9, 0x6a, 0xea, 0xab, 0xd3, 0xd5, 0xd4, 0xcf, 0x4f, 0x57, 0x53,
13815
+	0xff, 0x72, 0xba, 0x9a, 0xda, 0xcd, 0x8b, 0x1d, 0xe3, 0xc1, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff,
13816
+	0x55, 0x06, 0x85, 0xd6, 0xa6, 0x29, 0x00, 0x00,
13805 13817
 }
... ...
@@ -14,11 +14,20 @@ message Version {
14 14
 	uint64 index = 1;
15 15
 }
16 16
 
17
+message IndexEntry {
18
+	string key = 1;
19
+	string val = 2;
20
+}
21
+
17 22
 // Annotations provide useful information to identify API objects. They are
18 23
 // common to all API specs.
19 24
 message Annotations {
20 25
 	string name = 1;
21 26
 	map<string, string> labels = 2;
27
+
28
+	// Indices provides keys and values for indexing this object.
29
+	// A single key may have multiple values.
30
+	repeated IndexEntry indices = 4 [(gogoproto.nullable) = false];
22 31
 }
23 32
 
24 33
 message Resources {
... ...
@@ -315,6 +324,17 @@ message UpdateConfig {
315 315
 	// roll back to the previous service spec. If the MaxFailureRatio
316 316
 	// threshold is hit during the rollback, the rollback will pause.
317 317
 	float max_failure_ratio = 5;
318
+
319
+	// UpdateOrder controls the order of operations when rolling out an
320
+	// updated task. Either the old task is shut down before the new task
321
+	// is started, or the new task is started before the old task is shut
322
+	// down.
323
+	enum UpdateOrder {
324
+		STOP_FIRST = 0;
325
+		START_FIRST = 1;
326
+	}
327
+
328
+	UpdateOrder order = 6;
318 329
 }
319 330
 
320 331
 // UpdateStatus is the status of an update in progress.
... ...
@@ -635,6 +655,9 @@ message ExternalCA {
635 635
 	// Options is a set of additional key/value pairs whose interpretation
636 636
 	// depends on the specified CA type.
637 637
 	map<string, string> options = 3;
638
+
639
+	// CACert specifies which root CA is used by this external CA
640
+	bytes ca_cert = 4 [(gogoproto.customname) = "CACert"];
638 641
 }
639 642
 
640 643
 message CAConfig {
... ...
@@ -744,6 +767,10 @@ message RootCA {
744 744
 
745 745
 	// JoinTokens contains the join tokens for workers and managers.
746 746
 	JoinTokens join_tokens = 4 [(gogoproto.nullable) = false];
747
+
748
+	// RootRotation contains the new root cert and key we want to rotate to - if this is nil, we are not in the
749
+	// middle of a root rotation
750
+	RootRotation root_rotation = 5;
747 751
 }
748 752
 
749 753
 
... ...
@@ -872,6 +899,11 @@ message HealthConfig {
872 872
 	// Retries is the number of consecutive failures needed to consider a
873 873
 	// container as unhealthy. Zero means inherit.
874 874
 	int32 retries = 4;
875
+
876
+	// Start period is the period for container initialization during
877
+	// which health check failures will note count towards the maximum
878
+	// number of retries.
879
+	google.protobuf.Duration start_period = 5;
875 880
 }
876 881
 
877 882
 message MaybeEncryptedRecord {
... ...
@@ -884,3 +916,11 @@ message MaybeEncryptedRecord {
884 884
 	bytes data = 2;
885 885
 	bytes nonce = 3;
886 886
 }
887
+
888
+
889
+message RootRotation {
890
+	bytes ca_cert = 1 [(gogoproto.customname) = "CACert"];
891
+	bytes ca_key = 2 [(gogoproto.customname) = "CAKey"];
892
+	// cross-signed CA cert is the CACert that has been cross-signed by the previous root
893
+	bytes cross_signed_ca_cert = 3 [(gogoproto.customname) = "CrossSignedCACert"];;
894
+}
... ...
@@ -111,18 +111,25 @@ type LocalSigner struct {
111 111
 	// Key will only be used by the original manager to put the private
112 112
 	// key-material in raft, no signing operations depend on it.
113 113
 	Key []byte
114
+
115
+	// Cert is one PEM encoded Certificate used as the signing CA.  It must correspond to the key.
116
+	Cert []byte
117
+
118
+	// just cached parsed values for validation, etc.
119
+	parsedCert   *x509.Certificate
120
+	cryptoSigner crypto.Signer
114 121
 }
115 122
 
116 123
 // RootCA is the representation of everything we need to sign certificates and/or to verify certificates
117 124
 //
118
-// RootCA.Cert:          [signing CA cert][CA cert1][CA cert2]
125
+// RootCA.Cert:          [CA cert1][CA cert2]
119 126
 // RootCA.Intermediates: [intermediate CA1][intermediate CA2][intermediate CA3]
120
-// RootCA.Signer.Key:    [signing CA key]
127
+// RootCA.signer.Cert:   [signing CA cert]
128
+// RootCA.signer.Key:    [signing CA key]
121 129
 //
122 130
 // Requirements:
123 131
 //
124
-// - [signing CA key] must be the private key for [signing CA cert]
125
-// - [signing CA cert] must be the first cert in RootCA.Cert
132
+// - [signing CA key] must be the private key for [signing CA cert], and either both or none must be provided
126 133
 //
127 134
 // - [intermediate CA1] must have the same public key and subject as [signing CA cert], because otherwise when
128 135
 //   appended to a leaf certificate, the intermediates will not form a chain (because [intermediate CA1] won't because
... ...
@@ -135,10 +142,29 @@ type LocalSigner struct {
135 135
 //   valid chain from [leaf signed by signing CA cert] to one of the root certs ([signing CA cert], [CA cert1], [CA cert2])
136 136
 //   using zero or more of the intermediate certs ([intermediate CA1][intermediate CA2][intermediate CA3]) as intermediates
137 137
 //
138
+// Example 1:  Simple root rotation
139
+// - Initial state:
140
+// 	 - RootCA.Cert:          [Root CA1 self-signed]
141
+// 	 - RootCA.Intermediates: []
142
+// 	 - RootCA.signer.Cert:   [Root CA1 self-signed]
143
+// 	 - Issued TLS cert:      [leaf signed by Root CA1]
144
+//
145
+// - Intermediate state (during root rotation):
146
+//   - RootCA.Cert:          [Root CA1 self-signed]
147
+//   - RootCA.Intermediates: [Root CA2 signed by Root CA1]
148
+//   - RootCA.signer.Cert:   [Root CA2 signed by Root CA1]
149
+//   - Issued TLS cert:      [leaf signed by Root CA2][Root CA2 signed by Root CA1]
150
+//
151
+// - Final state:
152
+//   - RootCA.Cert:          [Root CA2 self-signed]
153
+//   - RootCA.Intermediates: []
154
+//   - RootCA.signer.Cert:   [Root CA2 self-signed]
155
+//   - Issued TLS cert:      [leaf signed by Root CA2]
156
+//
138 157
 type RootCA struct {
139
-	// Cert contains a bundle of PEM encoded Certificate for the Root CA, the first one of which
140
-	// must correspond to the key in the local signer, if provided
141
-	Cert []byte
158
+	// Certs contains a bundle of self-signed, PEM encoded certificates for the Root CA to be used
159
+	// as the root of trust.
160
+	Certs []byte
142 161
 
143 162
 	// Intermediates contains a bundle of PEM encoded intermediate CA certificates to append to any
144 163
 	// issued TLS (leaf) certificates. The first one must have the same public key and subject as the
... ...
@@ -153,16 +179,16 @@ type RootCA struct {
153 153
 	Digest digest.Digest
154 154
 
155 155
 	// This signer will be nil if the node doesn't have the appropriate key material
156
-	Signer *LocalSigner
156
+	signer *LocalSigner
157 157
 }
158 158
 
159
-// CanSign ensures that the signer has all three necessary elements needed to operate
160
-func (rca *RootCA) CanSign() bool {
161
-	if rca.Cert == nil || rca.Pool == nil || rca.Signer == nil {
162
-		return false
159
+// Signer is an accessor for the local signer that returns an error if this root cannot sign.
160
+func (rca *RootCA) Signer() (*LocalSigner, error) {
161
+	if rca.Pool == nil || rca.signer == nil || len(rca.signer.Cert) == 0 || rca.signer.Signer == nil {
162
+		return nil, ErrNoValidSigner
163 163
 	}
164 164
 
165
-	return true
165
+	return rca.signer, nil
166 166
 }
167 167
 
168 168
 // IssueAndSaveNewCertificates generates a new key-pair, signs it with the local root-ca, and returns a
... ...
@@ -173,10 +199,6 @@ func (rca *RootCA) IssueAndSaveNewCertificates(kw KeyWriter, cn, ou, org string)
173 173
 		return nil, errors.Wrap(err, "error when generating new node certs")
174 174
 	}
175 175
 
176
-	if !rca.CanSign() {
177
-		return nil, ErrNoValidSigner
178
-	}
179
-
180 176
 	// Obtain a signed Certificate
181 177
 	certChain, err := rca.ParseValidateAndSignCSR(csr, cn, ou, org)
182 178
 	if err != nil {
... ...
@@ -322,13 +344,12 @@ func PrepareCSR(csrBytes []byte, cn, ou, org string) cfsigner.SignRequest {
322 322
 
323 323
 // ParseValidateAndSignCSR returns a signed certificate from a particular rootCA and a CSR.
324 324
 func (rca *RootCA) ParseValidateAndSignCSR(csrBytes []byte, cn, ou, org string) ([]byte, error) {
325
-	if !rca.CanSign() {
326
-		return nil, ErrNoValidSigner
327
-	}
328
-
329 325
 	signRequest := PrepareCSR(csrBytes, cn, ou, org)
330
-
331
-	cert, err := rca.Signer.Sign(signRequest)
326
+	signer, err := rca.Signer()
327
+	if err != nil {
328
+		return nil, err
329
+	}
330
+	cert, err := signer.Sign(signRequest)
332 331
 	if err != nil {
333 332
 		return nil, errors.Wrap(err, "failed to sign node certificate")
334 333
 	}
... ...
@@ -338,20 +359,12 @@ func (rca *RootCA) ParseValidateAndSignCSR(csrBytes []byte, cn, ou, org string)
338 338
 
339 339
 // CrossSignCACertificate takes a CA root certificate and generates an intermediate CA from it signed with the current root signer
340 340
 func (rca *RootCA) CrossSignCACertificate(otherCAPEM []byte) ([]byte, error) {
341
-	if !rca.CanSign() {
342
-		return nil, ErrNoValidSigner
343
-	}
344
-
345
-	// create a new cert with exactly the same parameters, including the public key and exact NotBefore and NotAfter
346
-	rootCert, err := helpers.ParseCertificatePEM(rca.Cert)
341
+	signer, err := rca.Signer()
347 342
 	if err != nil {
348
-		return nil, errors.Wrap(err, "could not parse old CA certificate")
349
-	}
350
-	rootSigner, err := helpers.ParsePrivateKeyPEM(rca.Signer.Key)
351
-	if err != nil {
352
-		return nil, errors.Wrap(err, "could not parse old CA key")
343
+		return nil, err
353 344
 	}
354 345
 
346
+	// create a new cert with exactly the same parameters, including the public key and exact NotBefore and NotAfter
355 347
 	newCert, err := helpers.ParseCertificatePEM(otherCAPEM)
356 348
 	if err != nil {
357 349
 		return nil, errors.New("could not parse new CA certificate")
... ...
@@ -361,7 +374,7 @@ func (rca *RootCA) CrossSignCACertificate(otherCAPEM []byte) ([]byte, error) {
361 361
 		return nil, errors.New("certificate not a CA")
362 362
 	}
363 363
 
364
-	derBytes, err := x509.CreateCertificate(cryptorand.Reader, newCert, rootCert, newCert.PublicKey, rootSigner)
364
+	derBytes, err := x509.CreateCertificate(cryptorand.Reader, newCert, signer.parsedCert, newCert.PublicKey, signer.cryptoSigner)
365 365
 	if err != nil {
366 366
 		return nil, errors.Wrap(err, "could not cross-sign new CA certificate using old CA material")
367 367
 	}
... ...
@@ -372,28 +385,34 @@ func (rca *RootCA) CrossSignCACertificate(otherCAPEM []byte) ([]byte, error) {
372 372
 	}), nil
373 373
 }
374 374
 
375
+func validateSignatureAlgorithm(cert *x509.Certificate) error {
376
+	switch cert.SignatureAlgorithm {
377
+	case x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512:
378
+		return nil
379
+	default:
380
+		return fmt.Errorf("unsupported signature algorithm: %s", cert.SignatureAlgorithm.String())
381
+	}
382
+}
383
+
375 384
 // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte
376 385
 // slices. key may be nil, and in this case NewRootCA will return a RootCA
377 386
 // without a signer.
378
-func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration, intermediates []byte) (RootCA, error) {
387
+func NewRootCA(rootCertBytes, signCertBytes, signKeyBytes []byte, certExpiry time.Duration, intermediates []byte) (RootCA, error) {
379 388
 	// Parse all the certificates in the cert bundle
380
-	parsedCerts, err := helpers.ParseCertificatesPEM(certBytes)
389
+	parsedCerts, err := helpers.ParseCertificatesPEM(rootCertBytes)
381 390
 	if err != nil {
382
-		return RootCA{}, err
391
+		return RootCA{}, errors.Wrap(err, "invalid root certificates")
383 392
 	}
384 393
 	// Check to see if we have at least one valid cert
385 394
 	if len(parsedCerts) < 1 {
386
-		return RootCA{}, errors.New("no valid Root CA certificates found")
395
+		return RootCA{}, errors.New("no valid root CA certificates found")
387 396
 	}
388 397
 
389 398
 	// Create a Pool with all of the certificates found
390 399
 	pool := x509.NewCertPool()
391 400
 	for _, cert := range parsedCerts {
392
-		switch cert.SignatureAlgorithm {
393
-		case x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512:
394
-			break
395
-		default:
396
-			return RootCA{}, fmt.Errorf("unsupported signature algorithm: %s", cert.SignatureAlgorithm.String())
401
+		if err := validateSignatureAlgorithm(cert); err != nil {
402
+			return RootCA{}, err
397 403
 		}
398 404
 		// Check to see if all of the certificates are valid, self-signed root CA certs
399 405
 		selfpool := x509.NewCertPool()
... ...
@@ -405,81 +424,42 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration, intermediat
405 405
 	}
406 406
 
407 407
 	// Calculate the digest for our Root CA bundle
408
-	digest := digest.FromBytes(certBytes)
409
-
410
-	// We do not yet support arbitrary chains of intermediates (e.g. the case of an offline root, and the swarm CA is an
411
-	// intermediate CA). We currently only intermediates for which the first intermediate is cross-signed version of the
412
-	// CA signing cert (the first cert of the root certs) for the purposes of root rotation.  If we wanted to support
413
-	// offline roots, we'd have to separate the CA signing cert from the self-signed root certs, but this intermediate
414
-	// validation logic should remain the same.  Either the first intermediate would BE the intermediate CA we sign with
415
-	// (in which case it'd have the same subject and public key), or it would be a cross-signed intermediate with the
416
-	// same subject and public key as our signing cert (which could be either an intermediate cert or a self-signed root
417
-	// cert).
408
+	digest := digest.FromBytes(rootCertBytes)
409
+
410
+	// The intermediates supplied must be able to chain up to the root certificates, so that when they are appended to
411
+	// a leaf certificate, the leaf certificate can be validated through the intermediates to the root certificates.
412
+	var intermediatePool *x509.CertPool
413
+	var parsedIntermediates []*x509.Certificate
418 414
 	if len(intermediates) > 0 {
419
-		parsedIntermediates, err := ValidateCertChain(pool, intermediates, false)
415
+		parsedIntermediates, err = ValidateCertChain(pool, intermediates, false)
420 416
 		if err != nil {
421 417
 			return RootCA{}, errors.Wrap(err, "invalid intermediate chain")
422 418
 		}
423
-		if !bytes.Equal(parsedIntermediates[0].RawSubject, parsedCerts[0].RawSubject) ||
424
-			!bytes.Equal(parsedIntermediates[0].RawSubjectPublicKeyInfo, parsedCerts[0].RawSubjectPublicKeyInfo) {
425
-			return RootCA{}, errors.New("invalid intermediate chain - the first intermediate must have the same subject and public key as the root")
419
+		intermediatePool = x509.NewCertPool()
420
+		for _, cert := range parsedIntermediates {
421
+			intermediatePool.AddCert(cert)
426 422
 		}
427 423
 	}
428 424
 
429
-	if len(keyBytes) == 0 {
430
-		// This RootCA does not have a valid signer
431
-		return RootCA{Cert: certBytes, Intermediates: intermediates, Digest: digest, Pool: pool}, nil
432
-	}
433
-
434
-	var (
435
-		passphraseStr              string
436
-		passphrase, passphrasePrev []byte
437
-		priv                       crypto.Signer
438
-	)
439
-
440
-	// Attempt two distinct passphrases, so we can do a hitless passphrase rotation
441
-	if passphraseStr = os.Getenv(PassphraseENVVar); passphraseStr != "" {
442
-		passphrase = []byte(passphraseStr)
443
-	}
444
-
445
-	if p := os.Getenv(PassphraseENVVarPrev); p != "" {
446
-		passphrasePrev = []byte(p)
447
-	}
448
-
449
-	// Attempt to decrypt the current private-key with the passphrases provided
450
-	priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrase)
451
-	if err != nil {
452
-		priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrasePrev)
425
+	var localSigner *LocalSigner
426
+	if len(signKeyBytes) != 0 || len(signCertBytes) != 0 {
427
+		localSigner, err = newLocalSigner(signKeyBytes, signCertBytes, certExpiry, pool, intermediatePool)
453 428
 		if err != nil {
454
-			return RootCA{}, errors.Wrap(err, "malformed private key")
429
+			return RootCA{}, err
455 430
 		}
456
-	}
457
-
458
-	// We will always use the first certificate inside of the root bundle as the active one
459
-	if err := ensureCertKeyMatch(parsedCerts[0], priv.Public()); err != nil {
460
-		return RootCA{}, err
461
-	}
462
-
463
-	signer, err := local.NewSigner(priv, parsedCerts[0], cfsigner.DefaultSigAlgo(priv), SigningPolicy(certExpiry))
464
-	if err != nil {
465
-		return RootCA{}, err
466
-	}
467 431
 
468
-	// If the key was loaded from disk unencrypted, but there is a passphrase set,
469
-	// ensure it is encrypted, so it doesn't hit raft in plain-text
470
-	keyBlock, _ := pem.Decode(keyBytes)
471
-	if keyBlock == nil {
472
-		// This RootCA does not have a valid signer.
473
-		return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil
474
-	}
475
-	if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) {
476
-		keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr)
477
-		if err != nil {
478
-			return RootCA{}, err
432
+		// If a signer is provided and there are intermediates, then either the first intermediate would be the signer CA
433
+		// certificate (in which case it'd have the same subject and public key), or it would be a cross-signed
434
+		// intermediate with the same subject and public key as our signing CA certificate (which could be either an
435
+		// intermediate cert or a self-signed root cert).
436
+		if len(parsedIntermediates) > 0 && (!bytes.Equal(parsedIntermediates[0].RawSubject, localSigner.parsedCert.RawSubject) ||
437
+			!bytes.Equal(parsedIntermediates[0].RawSubjectPublicKeyInfo, localSigner.parsedCert.RawSubjectPublicKeyInfo)) {
438
+			return RootCA{}, errors.New(
439
+				"invalid intermediate chain - the first intermediate must have the same subject and public key as the signing cert")
479 440
 		}
480 441
 	}
481 442
 
482
-	return RootCA{Signer: &LocalSigner{Signer: signer, Key: keyBytes}, Intermediates: intermediates, Digest: digest, Cert: certBytes, Pool: pool}, nil
443
+	return RootCA{signer: localSigner, Intermediates: intermediates, Digest: digest, Certs: rootCertBytes, Pool: pool}, nil
483 444
 }
484 445
 
485 446
 // ValidateCertChain checks checks that the certificates provided chain up to the root pool provided.  In addition
... ...
@@ -579,6 +559,78 @@ func ValidateCertChain(rootPool *x509.CertPool, certs []byte, allowExpired bool)
579 579
 	return parsedCerts, nil
580 580
 }
581 581
 
582
+// newLocalSigner validates the signing cert and signing key to create a local signer, which accepts a crypto signer and a cert
583
+func newLocalSigner(keyBytes, certBytes []byte, certExpiry time.Duration, rootPool, intermediatePool *x509.CertPool) (*LocalSigner, error) {
584
+	if len(keyBytes) == 0 || len(certBytes) == 0 {
585
+		return nil, errors.New("must provide both a signing key and a signing cert, or neither")
586
+	}
587
+
588
+	parsedCerts, err := helpers.ParseCertificatesPEM(certBytes)
589
+	if err != nil {
590
+		return nil, errors.Wrap(err, "invalid signing CA cert")
591
+	}
592
+	if len(parsedCerts) == 0 {
593
+		return nil, errors.New("no valid signing CA certificates found")
594
+	}
595
+	if err := validateSignatureAlgorithm(parsedCerts[0]); err != nil {
596
+		return nil, err
597
+	}
598
+	opts := x509.VerifyOptions{
599
+		Roots:         rootPool,
600
+		Intermediates: intermediatePool,
601
+	}
602
+	if _, err := parsedCerts[0].Verify(opts); err != nil {
603
+		return nil, errors.Wrap(err, "error while validating signing CA certificate against roots and intermediates")
604
+	}
605
+
606
+	var (
607
+		passphraseStr              string
608
+		passphrase, passphrasePrev []byte
609
+		priv                       crypto.Signer
610
+	)
611
+
612
+	// Attempt two distinct passphrases, so we can do a hitless passphrase rotation
613
+	if passphraseStr = os.Getenv(PassphraseENVVar); passphraseStr != "" {
614
+		passphrase = []byte(passphraseStr)
615
+	}
616
+
617
+	if p := os.Getenv(PassphraseENVVarPrev); p != "" {
618
+		passphrasePrev = []byte(p)
619
+	}
620
+
621
+	// Attempt to decrypt the current private-key with the passphrases provided
622
+	priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrase)
623
+	if err != nil {
624
+		priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrasePrev)
625
+		if err != nil {
626
+			return nil, errors.Wrap(err, "malformed private key")
627
+		}
628
+	}
629
+
630
+	// We will always use the first certificate inside of the root bundle as the active one
631
+	if err := ensureCertKeyMatch(parsedCerts[0], priv.Public()); err != nil {
632
+		return nil, err
633
+	}
634
+
635
+	signer, err := local.NewSigner(priv, parsedCerts[0], cfsigner.DefaultSigAlgo(priv), SigningPolicy(certExpiry))
636
+	if err != nil {
637
+		return nil, err
638
+	}
639
+
640
+	// If the key was loaded from disk unencrypted, but there is a passphrase set,
641
+	// ensure it is encrypted, so it doesn't hit raft in plain-text
642
+	// we don't have to check for nil, because if we couldn't pem-decode the bytes, then parsing above would have failed
643
+	keyBlock, _ := pem.Decode(keyBytes)
644
+	if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) {
645
+		keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr)
646
+		if err != nil {
647
+			return nil, errors.Wrap(err, "unable to encrypt signing CA key material")
648
+		}
649
+	}
650
+
651
+	return &LocalSigner{Cert: certBytes, Key: keyBytes, Signer: signer, parsedCert: parsedCerts[0], cryptoSigner: priv}, nil
652
+}
653
+
582 654
 func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error {
583 655
 	switch certPub := cert.PublicKey.(type) {
584 656
 	case *rsa.PublicKey:
... ...
@@ -620,6 +672,7 @@ func GetLocalRootCA(paths CertPaths) (RootCA, error) {
620 620
 
621 621
 		return RootCA{}, err
622 622
 	}
623
+	signingCert := cert
623 624
 
624 625
 	key, err := ioutil.ReadFile(paths.Key)
625 626
 	if err != nil {
... ...
@@ -629,9 +682,10 @@ func GetLocalRootCA(paths CertPaths) (RootCA, error) {
629 629
 		// There may not be a local key. It's okay to pass in a nil
630 630
 		// key. We'll get a root CA without a signer.
631 631
 		key = nil
632
+		signingCert = nil
632 633
 	}
633 634
 
634
-	return NewRootCA(cert, key, DefaultNodeCertExpiration, nil)
635
+	return NewRootCA(cert, signingCert, key, DefaultNodeCertExpiration, nil)
635 636
 }
636 637
 
637 638
 func getGRPCConnection(creds credentials.TransportCredentials, connBroker *connectionbroker.Broker, forceRemote bool) (*connectionbroker.Conn, error) {
... ...
@@ -686,12 +740,12 @@ func GetRemoteCA(ctx context.Context, d digest.Digest, connBroker *connectionbro
686 686
 
687 687
 	// NewRootCA will validate that the certificates are otherwise valid and create a RootCA object.
688 688
 	// Since there is no key, the certificate expiry does not matter and will not be used.
689
-	return NewRootCA(response.Certificate, nil, DefaultNodeCertExpiration, nil)
689
+	return NewRootCA(response.Certificate, nil, nil, DefaultNodeCertExpiration, nil)
690 690
 }
691 691
 
692 692
 // CreateRootCA creates a Certificate authority for a new Swarm Cluster, potentially
693 693
 // overwriting any existing CAs.
694
-func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) {
694
+func CreateRootCA(rootCN string) (RootCA, error) {
695 695
 	// Create a simple CSR for the CA using the default CA validator and policy
696 696
 	req := cfcsr.CertificateRequest{
697 697
 		CN:         rootCN,
... ...
@@ -705,16 +759,11 @@ func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) {
705 705
 		return RootCA{}, err
706 706
 	}
707 707
 
708
-	rootCA, err := NewRootCA(cert, key, DefaultNodeCertExpiration, nil)
708
+	rootCA, err := NewRootCA(cert, cert, key, DefaultNodeCertExpiration, nil)
709 709
 	if err != nil {
710 710
 		return RootCA{}, err
711 711
 	}
712 712
 
713
-	// save the cert to disk
714
-	if err := saveRootCA(rootCA, paths); err != nil {
715
-		return RootCA{}, err
716
-	}
717
-
718 713
 	return rootCA, nil
719 714
 }
720 715
 
... ...
@@ -818,7 +867,8 @@ func readCertValidity(kr KeyReader) (time.Time, time.Time, error) {
818 818
 
819 819
 }
820 820
 
821
-func saveRootCA(rootCA RootCA, paths CertPaths) error {
821
+// SaveRootCA saves a RootCA object to disk
822
+func SaveRootCA(rootCA RootCA, paths CertPaths) error {
822 823
 	// Make sure the necessary dirs exist and they are writable
823 824
 	err := os.MkdirAll(filepath.Dir(paths.Cert), 0755)
824 825
 	if err != nil {
... ...
@@ -826,7 +876,7 @@ func saveRootCA(rootCA RootCA, paths CertPaths) error {
826 826
 	}
827 827
 
828 828
 	// If the root certificate got returned successfully, save the rootCA to disk.
829
-	return ioutils.AtomicWriteFile(paths.Cert, rootCA.Cert, 0644)
829
+	return ioutils.AtomicWriteFile(paths.Cert, rootCA.Certs, 0644)
830 830
 }
831 831
 
832 832
 // GenerateNewCSR returns a newly generated key and CSR signed with said key
... ...
@@ -71,6 +71,8 @@ type SecurityConfig struct {
71 71
 	externalCA    *ExternalCA
72 72
 	keyReadWriter *KeyReadWriter
73 73
 
74
+	externalCAClientRootPool *x509.CertPool
75
+
74 76
 	ServerTLSCreds *MutableTLSCreds
75 77
 	ClientTLSCreds *MutableTLSCreds
76 78
 }
... ...
@@ -95,11 +97,12 @@ func NewSecurityConfig(rootCA *RootCA, krw *KeyReadWriter, clientTLSCreds, serve
95 95
 	}
96 96
 
97 97
 	return &SecurityConfig{
98
-		rootCA:         rootCA,
99
-		keyReadWriter:  krw,
100
-		externalCA:     NewExternalCA(rootCA, externalCATLSConfig),
101
-		ClientTLSCreds: clientTLSCreds,
102
-		ServerTLSCreds: serverTLSCreds,
98
+		rootCA:                   rootCA,
99
+		keyReadWriter:            krw,
100
+		externalCA:               NewExternalCA(rootCA, externalCATLSConfig),
101
+		ClientTLSCreds:           clientTLSCreds,
102
+		ServerTLSCreds:           serverTLSCreds,
103
+		externalCAClientRootPool: rootCA.Pool,
103 104
 	}
104 105
 }
105 106
 
... ...
@@ -126,18 +129,13 @@ func (s *SecurityConfig) KeyReader() KeyReader {
126 126
 	return s.keyReadWriter
127 127
 }
128 128
 
129
-// UpdateRootCA replaces the root CA with a new root CA based on the specified
130
-// certificate, key, and the number of hours the certificates issue should last.
131
-func (s *SecurityConfig) UpdateRootCA(cert, key []byte, certExpiry time.Duration) error {
129
+// UpdateRootCA replaces the root CA with a new root CA
130
+func (s *SecurityConfig) UpdateRootCA(rootCA *RootCA, externalCARootPool *x509.CertPool) error {
132 131
 	s.mu.Lock()
133 132
 	defer s.mu.Unlock()
134 133
 
135
-	rootCA, err := NewRootCA(cert, key, certExpiry, nil)
136
-	if err != nil {
137
-		return err
138
-	}
139
-
140
-	s.rootCA = &rootCA
134
+	s.rootCA = rootCA
135
+	s.externalCAClientRootPool = externalCARootPool
141 136
 	clientTLSConfig := s.ClientTLSCreds.Config()
142 137
 	return s.updateTLSCredentials(clientTLSConfig.Certificates)
143 138
 }
... ...
@@ -163,7 +161,7 @@ func (s *SecurityConfig) updateTLSCredentials(certificates []tls.Certificate) er
163 163
 	// config using a copy without a serverName specified.
164 164
 	s.externalCA.UpdateTLSConfig(&tls.Config{
165 165
 		Certificates: certificates,
166
-		RootCAs:      s.rootCA.Pool,
166
+		RootCAs:      s.externalCAClientRootPool,
167 167
 		MinVersion:   tls.VersionTLS12,
168 168
 	})
169 169
 
... ...
@@ -278,7 +276,7 @@ func DownloadRootCA(ctx context.Context, paths CertPaths, token string, connBrok
278 278
 	}
279 279
 
280 280
 	// Save root CA certificate to disk
281
-	if err = saveRootCA(rootCA, paths); err != nil {
281
+	if err = SaveRootCA(rootCA, paths); err != nil {
282 282
 		return RootCA{}, err
283 283
 	}
284 284
 
... ...
@@ -359,31 +357,14 @@ type CertificateRequestConfig struct {
359 359
 func (rootCA RootCA) CreateSecurityConfig(ctx context.Context, krw *KeyReadWriter, config CertificateRequestConfig) (*SecurityConfig, error) {
360 360
 	ctx = log.WithModule(ctx, "tls")
361 361
 
362
-	var (
363
-		tlsKeyPair *tls.Certificate
364
-		err        error
365
-	)
366
-
367
-	if rootCA.CanSign() {
368
-		// Create a new random ID for this certificate
369
-		cn := identity.NewID()
370
-		org := identity.NewID()
362
+	// Create a new random ID for this certificate
363
+	cn := identity.NewID()
364
+	org := identity.NewID()
371 365
 
372
-		proposedRole := ManagerRole
373
-		tlsKeyPair, err = rootCA.IssueAndSaveNewCertificates(krw, cn, proposedRole, org)
374
-		if err != nil {
375
-			log.G(ctx).WithFields(logrus.Fields{
376
-				"node.id":   cn,
377
-				"node.role": proposedRole,
378
-			}).WithError(err).Errorf("failed to issue and save new certificate")
379
-			return nil, err
380
-		}
381
-
382
-		log.G(ctx).WithFields(logrus.Fields{
383
-			"node.id":   cn,
384
-			"node.role": proposedRole,
385
-		}).Debug("issued new TLS certificate")
386
-	} else {
366
+	proposedRole := ManagerRole
367
+	tlsKeyPair, err := rootCA.IssueAndSaveNewCertificates(krw, cn, proposedRole, org)
368
+	switch errors.Cause(err) {
369
+	case ErrNoValidSigner:
387 370
 		// Request certificate issuance from a remote CA.
388 371
 		// Last argument is nil because at this point we don't have any valid TLS creds
389 372
 		tlsKeyPair, err = rootCA.RequestAndSaveNewCertificates(ctx, krw, config)
... ...
@@ -391,7 +372,19 @@ func (rootCA RootCA) CreateSecurityConfig(ctx context.Context, krw *KeyReadWrite
391 391
 			log.G(ctx).WithError(err).Error("failed to request save new certificate")
392 392
 			return nil, err
393 393
 		}
394
+	case nil:
395
+		log.G(ctx).WithFields(logrus.Fields{
396
+			"node.id":   cn,
397
+			"node.role": proposedRole,
398
+		}).Debug("issued new TLS certificate")
399
+	default:
400
+		log.G(ctx).WithFields(logrus.Fields{
401
+			"node.id":   cn,
402
+			"node.role": proposedRole,
403
+		}).WithError(err).Errorf("failed to issue and save new certificate")
404
+		return nil, err
394 405
 	}
406
+
395 407
 	// Create the Server TLS Credentials for this node. These will not be used by workers.
396 408
 	serverTLSCreds, err := rootCA.NewServerTLSCredentials(tlsKeyPair)
397 409
 	if err != nil {
... ...
@@ -16,7 +16,6 @@ import (
16 16
 	"github.com/cloudflare/cfssl/api"
17 17
 	"github.com/cloudflare/cfssl/config"
18 18
 	"github.com/cloudflare/cfssl/csr"
19
-	"github.com/cloudflare/cfssl/helpers"
20 19
 	"github.com/cloudflare/cfssl/signer"
21 20
 	"github.com/pkg/errors"
22 21
 	"golang.org/x/net/context"
... ...
@@ -107,20 +106,14 @@ func (eca *ExternalCA) Sign(ctx context.Context, req signer.SignRequest) (cert [
107 107
 // CrossSignRootCA takes a RootCA object, generates a CA CSR, sends a signing request with the CA CSR to the external
108 108
 // CFSSL API server in order to obtain a cross-signed root
109 109
 func (eca *ExternalCA) CrossSignRootCA(ctx context.Context, rca RootCA) ([]byte, error) {
110
-	if !rca.CanSign() {
111
-		return nil, errors.Wrap(ErrNoValidSigner, "cannot generate CSR for a cross-signed root")
112
-	}
113
-	rootCert, err := helpers.ParseCertificatePEM(rca.Cert)
114
-	if err != nil {
115
-		return nil, errors.Wrap(err, "could not parse CA certificate")
116
-	}
117
-	rootSigner, err := helpers.ParsePrivateKeyPEM(rca.Signer.Key)
118
-	if err != nil {
119
-		return nil, errors.Wrap(err, "could not parse old CA key")
120
-	}
121 110
 	// ExtractCertificateRequest generates a new key request, and we want to continue to use the old
122 111
 	// key.  However, ExtractCertificateRequest will also convert the pkix.Name to csr.Name, which we
123 112
 	// need in order to generate a signing request
113
+	rcaSigner, err := rca.Signer()
114
+	if err != nil {
115
+		return nil, err
116
+	}
117
+	rootCert := rcaSigner.parsedCert
124 118
 	cfCSRObj := csr.ExtractCertificateRequest(rootCert)
125 119
 
126 120
 	der, err := x509.CreateCertificateRequest(cryptorand.Reader, &x509.CertificateRequest{
... ...
@@ -132,7 +125,7 @@ func (eca *ExternalCA) CrossSignRootCA(ctx context.Context, rca RootCA) ([]byte,
132 132
 		DNSNames:                rootCert.DNSNames,
133 133
 		EmailAddresses:          rootCert.EmailAddresses,
134 134
 		IPAddresses:             rootCert.IPAddresses,
135
-	}, rootSigner)
135
+	}, rcaSigner.cryptoSigner)
136 136
 	if err != nil {
137 137
 		return nil, err
138 138
 	}
... ...
@@ -1,12 +1,15 @@
1 1
 package ca
2 2
 
3 3
 import (
4
+	"bytes"
4 5
 	"crypto/subtle"
6
+	"crypto/x509"
5 7
 	"sync"
6 8
 	"time"
7 9
 
8 10
 	"github.com/Sirupsen/logrus"
9 11
 	"github.com/docker/swarmkit/api"
12
+	"github.com/docker/swarmkit/api/equality"
10 13
 	"github.com/docker/swarmkit/identity"
11 14
 	"github.com/docker/swarmkit/log"
12 15
 	"github.com/docker/swarmkit/manager/state"
... ...
@@ -22,6 +25,13 @@ const (
22 22
 	defaultReconciliationRetryInterval = 10 * time.Second
23 23
 )
24 24
 
25
+// APISecurityConfigUpdater knows how to update a SecurityConfig from an api.Cluster object
26
+type APISecurityConfigUpdater interface {
27
+	UpdateRootCA(ctx context.Context, cluster *api.Cluster) error
28
+}
29
+
30
+var _ APISecurityConfigUpdater = &Server{}
31
+
25 32
 // Server is the CA and NodeCA API gRPC server.
26 33
 // TODO(aaronl): At some point we may want to have separate implementations of
27 34
 // CA, NodeCA, and other hypothetical future CA services. At the moment,
... ...
@@ -43,6 +53,14 @@ type Server struct {
43 43
 	// started is a channel which gets closed once the server is running
44 44
 	// and able to service RPCs.
45 45
 	started chan struct{}
46
+
47
+	// these are cached values to ensure we only update the security config when
48
+	// the cluster root CA and external CAs have changed - the cluster object
49
+	// can change for other reasons, and it would not be necessary to update
50
+	// the security config as a result
51
+	lastSeenClusterRootCA *api.RootCA
52
+	lastSeenExternalCAs   []*api.ExternalCA
53
+	secConfigMu           sync.Mutex
46 54
 }
47 55
 
48 56
 // DefaultCAConfig returns the default CA Config, with a default expiration.
... ...
@@ -109,9 +127,9 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer
109 109
 
110 110
 	var node *api.Node
111 111
 
112
-	event := state.EventUpdateNode{
112
+	event := api.EventUpdateNode{
113 113
 		Node:   &api.Node{ID: request.NodeID},
114
-		Checks: []state.NodeCheckFunc{state.NodeCheckID},
114
+		Checks: []api.NodeCheckFunc{state.NodeCheckID},
115 115
 	}
116 116
 
117 117
 	// Retrieve the current value of the certificate with this token, and create a watcher
... ...
@@ -158,7 +176,7 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer
158 158
 		select {
159 159
 		case event := <-updates:
160 160
 			switch v := event.(type) {
161
-			case state.EventUpdateNode:
161
+			case api.EventUpdateNode:
162 162
 				// We got an update on the certificate record. If the status is a final state,
163 163
 				// return the certificate.
164 164
 				if isFinalState(v.Node.Certificate.Status) {
... ...
@@ -361,7 +379,7 @@ func (s *Server) GetRootCACertificate(ctx context.Context, request *api.GetRootC
361 361
 	})
362 362
 
363 363
 	return &api.GetRootCACertificateResponse{
364
-		Certificate: s.securityConfig.RootCA().Cert,
364
+		Certificate: s.securityConfig.RootCA().Certs,
365 365
 	}, nil
366 366
 }
367 367
 
... ...
@@ -396,8 +414,8 @@ func (s *Server) Run(ctx context.Context) error {
396 396
 			nodes, err = store.FindNodes(readTx, store.All)
397 397
 			return err
398 398
 		},
399
-		state.EventCreateNode{},
400
-		state.EventUpdateNode{},
399
+		api.EventCreateNode{},
400
+		api.EventUpdateNode{},
401 401
 	)
402 402
 
403 403
 	// Do this after updateCluster has been called, so isRunning never
... ...
@@ -441,9 +459,9 @@ func (s *Server) Run(ctx context.Context) error {
441 441
 		select {
442 442
 		case event := <-updates:
443 443
 			switch v := event.(type) {
444
-			case state.EventCreateNode:
444
+			case api.EventCreateNode:
445 445
 				s.evaluateAndSignNodeCert(ctx, v.Node)
446
-			case state.EventUpdateNode:
446
+			case api.EventUpdateNode:
447 447
 				// If this certificate is already at a final state
448 448
 				// no need to evaluate and sign it.
449 449
 				if !isFinalState(v.Node.Certificate.Status) {
... ...
@@ -517,65 +535,111 @@ func (s *Server) isRunning() bool {
517 517
 // UpdateRootCA is called when there are cluster changes, and it ensures that the local RootCA is
518 518
 // always aware of changes in clusterExpiry and the Root CA key material - this can be called by
519 519
 // anything to update the root CA material
520
-func (s *Server) UpdateRootCA(ctx context.Context, cluster *api.Cluster) {
520
+func (s *Server) UpdateRootCA(ctx context.Context, cluster *api.Cluster) error {
521 521
 	s.mu.Lock()
522 522
 	s.joinTokens = cluster.RootCA.JoinTokens.Copy()
523 523
 	s.mu.Unlock()
524
-	var err error
525 524
 
526
-	// If the cluster has a RootCA, let's try to update our SecurityConfig to reflect the latest values
525
+	s.secConfigMu.Lock()
526
+	defer s.secConfigMu.Unlock()
527
+	var err error
527 528
 	rCA := cluster.RootCA
528
-	if len(rCA.CACert) != 0 && len(rCA.CAKey) != 0 {
529
+	rootCAChanged := len(rCA.CACert) != 0 && !equality.RootCAEqualStable(s.lastSeenClusterRootCA, &cluster.RootCA)
530
+	externalCAChanged := !equality.ExternalCAsEqualStable(s.lastSeenExternalCAs, cluster.Spec.CAConfig.ExternalCAs)
531
+	logger := log.G(ctx).WithFields(logrus.Fields{
532
+		"cluster.id": cluster.ID,
533
+		"method":     "(*Server).UpdateRootCA",
534
+	})
535
+
536
+	if rootCAChanged {
537
+		logger.Debug("Updating security config due to change in cluster Root CA")
529 538
 		expiry := DefaultNodeCertExpiration
530 539
 		if cluster.Spec.CAConfig.NodeCertExpiry != nil {
531 540
 			// NodeCertExpiry exists, let's try to parse the duration out of it
532 541
 			clusterExpiry, err := gogotypes.DurationFromProto(cluster.Spec.CAConfig.NodeCertExpiry)
533 542
 			if err != nil {
534
-				log.G(ctx).WithFields(logrus.Fields{
535
-					"cluster.id": cluster.ID,
536
-					"method":     "(*Server).updateCluster",
537
-				}).WithError(err).Warn("failed to parse certificate expiration, using default")
543
+				logger.WithError(err).Warn("failed to parse certificate expiration, using default")
538 544
 			} else {
539 545
 				// We were able to successfully parse the expiration out of the cluster.
540 546
 				expiry = clusterExpiry
541 547
 			}
542 548
 		} else {
543 549
 			// NodeCertExpiry seems to be nil
544
-			log.G(ctx).WithFields(logrus.Fields{
545
-				"cluster.id": cluster.ID,
546
-				"method":     "(*Server).updateCluster",
547
-			}).WithError(err).Warn("failed to parse certificate expiration, using default")
548
-
550
+			logger.WithError(err).Warn("failed to parse certificate expiration, using default")
549 551
 		}
550 552
 		// Attempt to update our local RootCA with the new parameters
551
-		err = s.securityConfig.UpdateRootCA(rCA.CACert, rCA.CAKey, expiry)
553
+		var intermediates []byte
554
+		signingCert := rCA.CACert
555
+		signingKey := rCA.CAKey
556
+		if rCA.RootRotation != nil {
557
+			signingCert = rCA.RootRotation.CrossSignedCACert
558
+			signingKey = rCA.RootRotation.CAKey
559
+			intermediates = rCA.RootRotation.CrossSignedCACert
560
+		}
561
+		if signingKey == nil {
562
+			signingCert = nil
563
+		}
564
+
565
+		updatedRootCA, err := NewRootCA(rCA.CACert, signingCert, signingKey, expiry, intermediates)
552 566
 		if err != nil {
553
-			log.G(ctx).WithFields(logrus.Fields{
554
-				"cluster.id": cluster.ID,
555
-				"method":     "(*Server).updateCluster",
556
-			}).WithError(err).Error("updating Root CA failed")
557
-		} else {
558
-			log.G(ctx).WithFields(logrus.Fields{
559
-				"cluster.id": cluster.ID,
560
-				"method":     "(*Server).updateCluster",
561
-			}).Debugf("Root CA updated successfully")
567
+			return errors.Wrap(err, "invalid Root CA object in cluster")
562 568
 		}
563
-	}
564 569
 
565
-	// Update our security config with the list of External CA URLs
566
-	// from the new cluster state.
570
+		externalCARootPool := updatedRootCA.Pool
571
+		if rCA.RootRotation != nil {
572
+			// the external CA has to trust the new CA cert
573
+			externalCARootPool = x509.NewCertPool()
574
+			externalCARootPool.AppendCertsFromPEM(rCA.CACert)
575
+			externalCARootPool.AppendCertsFromPEM(rCA.RootRotation.CACert)
576
+		}
567 577
 
568
-	// TODO(aaronl): In the future, this will be abstracted with an
569
-	// ExternalCA interface that has different implementations for
570
-	// different CA types. At the moment, only CFSSL is supported.
571
-	var cfsslURLs []string
572
-	for _, ca := range cluster.Spec.CAConfig.ExternalCAs {
573
-		if ca.Protocol == api.ExternalCA_CAProtocolCFSSL {
574
-			cfsslURLs = append(cfsslURLs, ca.URL)
578
+		// Attempt to update our local RootCA with the new parameters
579
+		if err := s.securityConfig.UpdateRootCA(&updatedRootCA, externalCARootPool); err != nil {
580
+			return errors.Wrap(err, "updating Root CA failed")
581
+		}
582
+		// only update the server cache if we've successfully updated the root CA
583
+		logger.Debug("Root CA updated successfully")
584
+		s.lastSeenClusterRootCA = cluster.RootCA.Copy()
585
+	}
586
+
587
+	// we want to update if the external CA changed, or if the root CA changed because the root CA could affect what
588
+	// certificate for external CAs we want to filter by
589
+	if rootCAChanged || externalCAChanged {
590
+		logger.Debug("Updating security config due to change in cluster Root CA or cluster spec")
591
+		wantedExternalCACert := rCA.CACert // we want to only add external CA URLs that use this cert
592
+		if rCA.RootRotation != nil {
593
+			// we're rotating to a new root, so we only want external CAs with the new root cert
594
+			wantedExternalCACert = rCA.RootRotation.CACert
595
+		}
596
+		// Update our security config with the list of External CA URLs
597
+		// from the new cluster state.
598
+
599
+		// TODO(aaronl): In the future, this will be abstracted with an
600
+		// ExternalCA interface that has different implementations for
601
+		// different CA types. At the moment, only CFSSL is supported.
602
+		var cfsslURLs []string
603
+		for i, extCA := range cluster.Spec.CAConfig.ExternalCAs {
604
+			// We want to support old external CA specifications which did not have a CA cert.  If there is no cert specified,
605
+			// we assume it's the old cert
606
+			certForExtCA := extCA.CACert
607
+			if len(certForExtCA) == 0 {
608
+				certForExtCA = rCA.CACert
609
+			}
610
+			if extCA.Protocol != api.ExternalCA_CAProtocolCFSSL {
611
+				logger.Debugf("skipping external CA %d (url: %s) due to unknown protocol type", i, extCA.URL)
612
+				continue
613
+			}
614
+			if !bytes.Equal(certForExtCA, wantedExternalCACert) {
615
+				logger.Debugf("skipping external CA %d (url: %s) because it has the wrong CA cert", i, extCA.URL)
616
+				continue
617
+			}
618
+			cfsslURLs = append(cfsslURLs, extCA.URL)
575 619
 		}
576
-	}
577 620
 
578
-	s.securityConfig.externalCA.UpdateURLs(cfsslURLs...)
621
+		s.securityConfig.externalCA.UpdateURLs(cfsslURLs...)
622
+		s.lastSeenExternalCAs = cluster.Spec.CAConfig.Copy().ExternalCAs
623
+	}
624
+	return nil
579 625
 }
580 626
 
581 627
 // evaluateAndSignNodeCert implements the logic of which certificates to sign
... ...
@@ -5,6 +5,7 @@ import (
5 5
 
6 6
 	"github.com/docker/docker/pkg/plugingetter"
7 7
 	"github.com/docker/go-events"
8
+	"github.com/docker/swarmkit/api"
8 9
 	"github.com/docker/swarmkit/manager/state"
9 10
 	"github.com/docker/swarmkit/manager/state/store"
10 11
 	"golang.org/x/net/context"
... ...
@@ -99,17 +100,17 @@ func (a *Allocator) Run(ctx context.Context) error {
99 99
 
100 100
 	var actors []func() error
101 101
 	watch, watchCancel := state.Watch(a.store.WatchQueue(),
102
-		state.EventCreateNetwork{},
103
-		state.EventDeleteNetwork{},
104
-		state.EventCreateService{},
105
-		state.EventUpdateService{},
106
-		state.EventDeleteService{},
107
-		state.EventCreateTask{},
108
-		state.EventUpdateTask{},
109
-		state.EventDeleteTask{},
110
-		state.EventCreateNode{},
111
-		state.EventUpdateNode{},
112
-		state.EventDeleteNode{},
102
+		api.EventCreateNetwork{},
103
+		api.EventDeleteNetwork{},
104
+		api.EventCreateService{},
105
+		api.EventUpdateService{},
106
+		api.EventDeleteService{},
107
+		api.EventCreateTask{},
108
+		api.EventUpdateTask{},
109
+		api.EventDeleteTask{},
110
+		api.EventCreateNode{},
111
+		api.EventUpdateNode{},
112
+		api.EventDeleteNode{},
113 113
 		state.EventCommit{},
114 114
 	)
115 115
 
... ...
@@ -258,7 +258,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
258 258
 	nc := a.netCtx
259 259
 
260 260
 	switch v := ev.(type) {
261
-	case state.EventCreateNetwork:
261
+	case api.EventCreateNetwork:
262 262
 		n := v.Network.Copy()
263 263
 		if nc.nwkAllocator.IsAllocated(n) {
264 264
 			break
... ...
@@ -288,7 +288,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
288 288
 				log.G(ctx).WithError(err).Error(err)
289 289
 			}
290 290
 		}
291
-	case state.EventDeleteNetwork:
291
+	case api.EventDeleteNetwork:
292 292
 		n := v.Network.Copy()
293 293
 
294 294
 		if IsIngressNetwork(n) && nc.ingressNetwork.ID == n.ID {
... ...
@@ -307,8 +307,15 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
307 307
 		}
308 308
 
309 309
 		delete(nc.unallocatedNetworks, n.ID)
310
-	case state.EventCreateService:
311
-		s := v.Service.Copy()
310
+	case api.EventCreateService:
311
+		var s *api.Service
312
+		a.store.View(func(tx store.ReadTx) {
313
+			s = store.GetService(tx, v.Service.ID)
314
+		})
315
+
316
+		if s == nil {
317
+			break
318
+		}
312 319
 
313 320
 		if nc.nwkAllocator.IsServiceAllocated(s) {
314 321
 			break
... ...
@@ -324,8 +331,19 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
324 324
 		}); err != nil {
325 325
 			log.G(ctx).WithError(err).Errorf("Failed to commit allocation for service %s", s.ID)
326 326
 		}
327
-	case state.EventUpdateService:
328
-		s := v.Service.Copy()
327
+	case api.EventUpdateService:
328
+		// We may have already allocated this service. If a create or
329
+		// update event is older than the current version in the store,
330
+		// we run the risk of allocating the service a second time.
331
+		// Only operate on the latest version of the service.
332
+		var s *api.Service
333
+		a.store.View(func(tx store.ReadTx) {
334
+			s = store.GetService(tx, v.Service.ID)
335
+		})
336
+
337
+		if s == nil {
338
+			break
339
+		}
329 340
 
330 341
 		if nc.nwkAllocator.IsServiceAllocated(s) {
331 342
 			if nc.nwkAllocator.PortsAllocatedInHostPublishMode(s) {
... ...
@@ -347,7 +365,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
347 347
 		} else {
348 348
 			delete(nc.unallocatedServices, s.ID)
349 349
 		}
350
-	case state.EventDeleteService:
350
+	case api.EventDeleteService:
351 351
 		s := v.Service.Copy()
352 352
 
353 353
 		if err := nc.nwkAllocator.ServiceDeallocate(s); err != nil {
... ...
@@ -357,9 +375,9 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
357 357
 		// Remove it from unallocatedServices just in case
358 358
 		// it's still there.
359 359
 		delete(nc.unallocatedServices, s.ID)
360
-	case state.EventCreateNode, state.EventUpdateNode, state.EventDeleteNode:
360
+	case api.EventCreateNode, api.EventUpdateNode, api.EventDeleteNode:
361 361
 		a.doNodeAlloc(ctx, ev)
362
-	case state.EventCreateTask, state.EventUpdateTask, state.EventDeleteTask:
362
+	case api.EventCreateTask, api.EventUpdateTask, api.EventDeleteTask:
363 363
 		a.doTaskAlloc(ctx, ev)
364 364
 	case state.EventCommit:
365 365
 		a.procTasksNetwork(ctx, false)
... ...
@@ -385,16 +403,28 @@ func (a *Allocator) doNodeAlloc(ctx context.Context, ev events.Event) {
385 385
 		node     *api.Node
386 386
 	)
387 387
 
388
+	// We may have already allocated this node. If a create or update
389
+	// event is older than the current version in the store, we run the
390
+	// risk of allocating the node a second time. Only operate on the
391
+	// latest version of the node.
388 392
 	switch v := ev.(type) {
389
-	case state.EventCreateNode:
390
-		node = v.Node.Copy()
391
-	case state.EventUpdateNode:
392
-		node = v.Node.Copy()
393
-	case state.EventDeleteNode:
393
+	case api.EventCreateNode:
394
+		a.store.View(func(tx store.ReadTx) {
395
+			node = store.GetNode(tx, v.Node.ID)
396
+		})
397
+	case api.EventUpdateNode:
398
+		a.store.View(func(tx store.ReadTx) {
399
+			node = store.GetNode(tx, v.Node.ID)
400
+		})
401
+	case api.EventDeleteNode:
394 402
 		isDelete = true
395 403
 		node = v.Node.Copy()
396 404
 	}
397 405
 
406
+	if node == nil {
407
+		return
408
+	}
409
+
398 410
 	nc := a.netCtx
399 411
 
400 412
 	if isDelete {
... ...
@@ -530,7 +560,8 @@ func taskUpdateEndpoint(t *api.Task, endpoint *api.Endpoint) {
530 530
 	t.Endpoint = endpoint.Copy()
531 531
 }
532 532
 
533
-func isIngressNetworkNeeded(s *api.Service) bool {
533
+// IsIngressNetworkNeeded checks whether the service requires the routing-mesh
534
+func IsIngressNetworkNeeded(s *api.Service) bool {
534 535
 	if s == nil {
535 536
 		return false
536 537
 	}
... ...
@@ -560,7 +591,7 @@ func (a *Allocator) taskCreateNetworkAttachments(t *api.Task, s *api.Service) {
560 560
 	}
561 561
 
562 562
 	var networks []*api.NetworkAttachment
563
-	if isIngressNetworkNeeded(s) {
563
+	if IsIngressNetworkNeeded(s) {
564 564
 		networks = append(networks, &api.NetworkAttachment{Network: a.netCtx.ingressNetwork})
565 565
 	}
566 566
 
... ...
@@ -594,16 +625,28 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, ev events.Event) {
594 594
 		t        *api.Task
595 595
 	)
596 596
 
597
+	// We may have already allocated this task. If a create or update
598
+	// event is older than the current version in the store, we run the
599
+	// risk of allocating the task a second time. Only operate on the
600
+	// latest version of the task.
597 601
 	switch v := ev.(type) {
598
-	case state.EventCreateTask:
599
-		t = v.Task.Copy()
600
-	case state.EventUpdateTask:
601
-		t = v.Task.Copy()
602
-	case state.EventDeleteTask:
602
+	case api.EventCreateTask:
603
+		a.store.View(func(tx store.ReadTx) {
604
+			t = store.GetTask(tx, v.Task.ID)
605
+		})
606
+	case api.EventUpdateTask:
607
+		a.store.View(func(tx store.ReadTx) {
608
+			t = store.GetTask(tx, v.Task.ID)
609
+		})
610
+	case api.EventDeleteTask:
603 611
 		isDelete = true
604 612
 		t = v.Task.Copy()
605 613
 	}
606 614
 
615
+	if t == nil {
616
+		return
617
+	}
618
+
607 619
 	nc := a.netCtx
608 620
 
609 621
 	// If the task has stopped running then we should free the network
... ...
@@ -728,7 +771,7 @@ func (a *Allocator) allocateService(ctx context.Context, s *api.Service) error {
728 728
 		// The service is trying to expose ports to the external
729 729
 		// world. Automatically attach the service to the ingress
730 730
 		// network only if it is not already done.
731
-		if isIngressNetworkNeeded(s) {
731
+		if IsIngressNetworkNeeded(s) {
732 732
 			if nc.ingressNetwork == nil {
733 733
 				return fmt.Errorf("ingress network is missing")
734 734
 			}
... ...
@@ -761,7 +804,7 @@ func (a *Allocator) allocateService(ctx context.Context, s *api.Service) error {
761 761
 	// If the service doesn't expose ports any more and if we have
762 762
 	// any lingering virtual IP references for ingress network
763 763
 	// clean them up here.
764
-	if !isIngressNetworkNeeded(s) {
764
+	if !IsIngressNetworkNeeded(s) {
765 765
 		if s.Endpoint != nil {
766 766
 			for i, vip := range s.Endpoint.VirtualIPs {
767 767
 				if vip.NetworkID == nc.ingressNetwork.ID {
... ...
@@ -870,7 +913,7 @@ func (a *Allocator) allocateTask(ctx context.Context, t *api.Task) (err error) {
870 870
 			}
871 871
 
872 872
 			if err = nc.nwkAllocator.AllocateTask(t); err != nil {
873
-				err = errors.Wrapf(err, "failed during networktask allocation for task %s", t.ID)
873
+				err = errors.Wrapf(err, "failed during network allocation for task %s", t.ID)
874 874
 				return
875 875
 			}
876 876
 			if nc.nwkAllocator.IsTaskAllocated(t) {
... ...
@@ -6,6 +6,7 @@ import (
6 6
 
7 7
 	"github.com/docker/swarmkit/api"
8 8
 	"github.com/docker/swarmkit/ca"
9
+	"github.com/docker/swarmkit/log"
9 10
 	"github.com/docker/swarmkit/manager/encryption"
10 11
 	"github.com/docker/swarmkit/manager/state/store"
11 12
 	gogotypes "github.com/gogo/protobuf/types"
... ...
@@ -104,16 +105,28 @@ func (s *Server) UpdateCluster(ctx context.Context, request *api.UpdateClusterRe
104 104
 			return grpc.Errorf(codes.NotFound, "cluster %s not found", request.ClusterID)
105 105
 
106 106
 		}
107
+		// This ensures that we always have the latest security config, so our ca.SecurityConfig.RootCA and
108
+		// ca.SecurityConfig.externalCA objects are up-to-date with the current api.Cluster.RootCA and
109
+		// api.Cluster.Spec.ExternalCA objects, respectively.  Note that if, during this update, the cluster gets
110
+		// updated again with different CA info and the security config gets changed under us, that's still fine because
111
+		// this cluster update would fail anyway due to its version being too low on write.
112
+		if err := s.scu.UpdateRootCA(ctx, cluster); err != nil {
113
+			log.G(ctx).WithField(
114
+				"method", "(*controlapi.Server).UpdateCluster").WithError(err).Error("could not update security config")
115
+			return grpc.Errorf(codes.Internal, "could not update security config")
116
+		}
117
+		rootCA := s.securityConfig.RootCA()
118
+
107 119
 		cluster.Meta.Version = *request.ClusterVersion
108 120
 		cluster.Spec = *request.Spec.Copy()
109 121
 
110 122
 		expireBlacklistedCerts(cluster)
111 123
 
112 124
 		if request.Rotation.WorkerJoinToken {
113
-			cluster.RootCA.JoinTokens.Worker = ca.GenerateJoinToken(s.rootCA)
125
+			cluster.RootCA.JoinTokens.Worker = ca.GenerateJoinToken(rootCA)
114 126
 		}
115 127
 		if request.Rotation.ManagerJoinToken {
116
-			cluster.RootCA.JoinTokens.Manager = ca.GenerateJoinToken(s.rootCA)
128
+			cluster.RootCA.JoinTokens.Manager = ca.GenerateJoinToken(rootCA)
117 129
 		}
118 130
 
119 131
 		var unlockKeys []*api.EncryptionKey
... ...
@@ -219,7 +219,7 @@ func (s *Server) removeIngressNetwork(id string) error {
219 219
 			return grpc.Errorf(codes.Internal, "could not find services using network %s: %v", id, err)
220 220
 		}
221 221
 		for _, srv := range services {
222
-			if doesServiceNeedIngress(srv) {
222
+			if allocator.IsIngressNetworkNeeded(srv) {
223 223
 				return grpc.Errorf(codes.FailedPrecondition, "ingress network cannot be removed because service %s depends on it", srv.ID)
224 224
 			}
225 225
 		}
... ...
@@ -16,18 +16,21 @@ var (
16 16
 
17 17
 // Server is the Cluster API gRPC server.
18 18
 type Server struct {
19
-	store  *store.MemoryStore
20
-	raft   *raft.Node
21
-	rootCA *ca.RootCA
22
-	pg     plugingetter.PluginGetter
19
+	store          *store.MemoryStore
20
+	raft           *raft.Node
21
+	securityConfig *ca.SecurityConfig
22
+	scu            ca.APISecurityConfigUpdater
23
+	pg             plugingetter.PluginGetter
23 24
 }
24 25
 
25 26
 // NewServer creates a Cluster API server.
26
-func NewServer(store *store.MemoryStore, raft *raft.Node, rootCA *ca.RootCA, pg plugingetter.PluginGetter) *Server {
27
+func NewServer(store *store.MemoryStore, raft *raft.Node, securityConfig *ca.SecurityConfig,
28
+	scu ca.APISecurityConfigUpdater, pg plugingetter.PluginGetter) *Server {
27 29
 	return &Server{
28
-		store:  store,
29
-		raft:   raft,
30
-		rootCA: rootCA,
31
-		pg:     pg,
30
+		store:          store,
31
+		raft:           raft,
32
+		securityConfig: securityConfig,
33
+		scu:            scu,
34
+		pg:             pg,
32 35
 	}
33 36
 }
... ...
@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 	"github.com/docker/distribution/reference"
12 12
 	"github.com/docker/swarmkit/api"
13
+	"github.com/docker/swarmkit/api/naming"
13 14
 	"github.com/docker/swarmkit/identity"
14 15
 	"github.com/docker/swarmkit/manager/allocator"
15 16
 	"github.com/docker/swarmkit/manager/constraint"
... ...
@@ -23,7 +24,7 @@ import (
23 23
 )
24 24
 
25 25
 var (
26
-	errNetworkUpdateNotSupported = errors.New("changing network in service is not supported")
26
+	errNetworkUpdateNotSupported = errors.New("networks must be migrated to TaskSpec before being changed")
27 27
 	errRenameNotSupported        = errors.New("renaming services is not supported")
28 28
 	errModeChangeNotAllowed      = errors.New("service mode change is not allowed")
29 29
 )
... ...
@@ -118,9 +119,27 @@ func validateUpdate(uc *api.UpdateConfig) error {
118 118
 	return nil
119 119
 }
120 120
 
121
-func validateContainerSpec(container *api.ContainerSpec) error {
122
-	if container == nil {
123
-		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: missing in service spec")
121
+func validateContainerSpec(taskSpec api.TaskSpec) error {
122
+	// Building a empty/dummy Task to validate the templating and
123
+	// the resulting container spec as well. This is a *best effort*
124
+	// validation.
125
+	container, err := template.ExpandContainerSpec(&api.Task{
126
+		Spec:      taskSpec,
127
+		ServiceID: "serviceid",
128
+		Slot:      1,
129
+		NodeID:    "nodeid",
130
+		Networks:  []*api.NetworkAttachment{},
131
+		Annotations: api.Annotations{
132
+			Name: "taskname",
133
+		},
134
+		ServiceAnnotations: api.Annotations{
135
+			Name: "servicename",
136
+		},
137
+		Endpoint:  &api.Endpoint{},
138
+		LogDriver: taskSpec.LogDriver,
139
+	})
140
+	if err != nil {
141
+		return grpc.Errorf(codes.InvalidArgument, err.Error())
124 142
 	}
125 143
 
126 144
 	if container.Image == "" {
... ...
@@ -142,6 +161,37 @@ func validateContainerSpec(container *api.ContainerSpec) error {
142 142
 	return nil
143 143
 }
144 144
 
145
+func validateGenericRuntimeSpec(taskSpec api.TaskSpec) error {
146
+	generic := taskSpec.GetGeneric()
147
+
148
+	if len(generic.Kind) < 3 {
149
+		return grpc.Errorf(codes.InvalidArgument, "Generic runtime: Invalid name %q", generic.Kind)
150
+	}
151
+
152
+	reservedNames := []string{"container", "attachment"}
153
+	for _, n := range reservedNames {
154
+		if strings.ToLower(generic.Kind) == n {
155
+			return grpc.Errorf(codes.InvalidArgument, "Generic runtime: %q is a reserved name", generic.Kind)
156
+		}
157
+	}
158
+
159
+	payload := generic.Payload
160
+
161
+	if payload == nil {
162
+		return grpc.Errorf(codes.InvalidArgument, "Generic runtime is missing payload")
163
+	}
164
+
165
+	if payload.TypeUrl == "" {
166
+		return grpc.Errorf(codes.InvalidArgument, "Generic runtime is missing payload type")
167
+	}
168
+
169
+	if len(payload.Value) == 0 {
170
+		return grpc.Errorf(codes.InvalidArgument, "Generic runtime has an empty payload")
171
+	}
172
+
173
+	return nil
174
+}
175
+
145 176
 func validateTaskSpec(taskSpec api.TaskSpec) error {
146 177
 	if err := validateResourceRequirements(taskSpec.Resources); err != nil {
147 178
 		return err
... ...
@@ -164,36 +214,19 @@ func validateTaskSpec(taskSpec api.TaskSpec) error {
164 164
 		return grpc.Errorf(codes.InvalidArgument, "TaskSpec: missing runtime")
165 165
 	}
166 166
 
167
-	_, ok := taskSpec.GetRuntime().(*api.TaskSpec_Container)
168
-	if !ok {
167
+	switch taskSpec.GetRuntime().(type) {
168
+	case *api.TaskSpec_Container:
169
+		if err := validateContainerSpec(taskSpec); err != nil {
170
+			return err
171
+		}
172
+	case *api.TaskSpec_Generic:
173
+		if err := validateGenericRuntimeSpec(taskSpec); err != nil {
174
+			return err
175
+		}
176
+	default:
169 177
 		return grpc.Errorf(codes.Unimplemented, "RuntimeSpec: unimplemented runtime in service spec")
170 178
 	}
171 179
 
172
-	// Building a empty/dummy Task to validate the templating and
173
-	// the resulting container spec as well. This is a *best effort*
174
-	// validation.
175
-	preparedSpec, err := template.ExpandContainerSpec(&api.Task{
176
-		Spec:      taskSpec,
177
-		ServiceID: "serviceid",
178
-		Slot:      1,
179
-		NodeID:    "nodeid",
180
-		Networks:  []*api.NetworkAttachment{},
181
-		Annotations: api.Annotations{
182
-			Name: "taskname",
183
-		},
184
-		ServiceAnnotations: api.Annotations{
185
-			Name: "servicename",
186
-		},
187
-		Endpoint:  &api.Endpoint{},
188
-		LogDriver: taskSpec.LogDriver,
189
-	})
190
-	if err != nil {
191
-		return grpc.Errorf(codes.InvalidArgument, err.Error())
192
-	}
193
-	if err := validateContainerSpec(preparedSpec); err != nil {
194
-		return err
195
-	}
196
-
197 180
 	return nil
198 181
 }
199 182
 
... ...
@@ -425,36 +458,6 @@ func (s *Server) checkSecretExistence(tx store.Tx, spec *api.ServiceSpec) error
425 425
 	return nil
426 426
 }
427 427
 
428
-func doesServiceNeedIngress(srv *api.Service) bool {
429
-	// Only VIP mode with target ports needs routing mesh.
430
-	// If no endpoint is specified, it defaults to VIP mode but no target ports
431
-	// are specified, so the service does not need the routing mesh.
432
-	if srv.Spec.Endpoint == nil || srv.Spec.Endpoint.Mode != api.ResolutionModeVirtualIP {
433
-		return false
434
-	}
435
-	// Go through the ports' config
436
-	for _, p := range srv.Spec.Endpoint.Ports {
437
-		if p.PublishMode != api.PublishModeIngress {
438
-			continue
439
-		}
440
-		if p.PublishedPort != 0 {
441
-			return true
442
-		}
443
-	}
444
-	// Go through the ports' state
445
-	if srv.Endpoint != nil {
446
-		for _, p := range srv.Endpoint.Ports {
447
-			if p.PublishMode != api.PublishModeIngress {
448
-				continue
449
-			}
450
-			if p.PublishedPort != 0 {
451
-				return true
452
-			}
453
-		}
454
-	}
455
-	return false
456
-}
457
-
458 428
 // CreateService creates and returns a Service based on the provided ServiceSpec.
459 429
 // - Returns `InvalidArgument` if the ServiceSpec is malformed.
460 430
 // - Returns `Unimplemented` if the ServiceSpec references unimplemented features.
... ...
@@ -476,11 +479,12 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe
476 476
 	// TODO(aluzzardi): Consider using `Name` as a primary key to handle
477 477
 	// duplicate creations. See #65
478 478
 	service := &api.Service{
479
-		ID:   identity.NewID(),
480
-		Spec: *request.Spec,
479
+		ID:          identity.NewID(),
480
+		Spec:        *request.Spec,
481
+		SpecVersion: &api.Version{},
481 482
 	}
482 483
 
483
-	if doesServiceNeedIngress(service) {
484
+	if allocator.IsIngressNetworkNeeded(service) {
484 485
 		if _, err := allocator.GetIngressNetwork(s.store); err == allocator.ErrNoIngress {
485 486
 			return nil, grpc.Errorf(codes.FailedPrecondition, "service needs ingress network, but no ingress network is present")
486 487
 		}
... ...
@@ -558,18 +562,14 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
558 558
 		if service == nil {
559 559
 			return grpc.Errorf(codes.NotFound, "service %s not found", request.ServiceID)
560 560
 		}
561
-		// temporary disable network update
562
-		requestSpecNetworks := request.Spec.Task.Networks
563
-		if len(requestSpecNetworks) == 0 {
564
-			requestSpecNetworks = request.Spec.Networks
565
-		}
566
-
567
-		specNetworks := service.Spec.Task.Networks
568
-		if len(specNetworks) == 0 {
569
-			specNetworks = service.Spec.Networks
570
-		}
571 561
 
572
-		if !reflect.DeepEqual(requestSpecNetworks, specNetworks) {
562
+		// It's not okay to update Service.Spec.Networks on its own.
563
+		// However, if Service.Spec.Task.Networks is also being
564
+		// updated, that's okay (for example when migrating from the
565
+		// deprecated Spec.Networks field to Spec.Task.Networks).
566
+		if (len(request.Spec.Networks) != 0 || len(service.Spec.Networks) != 0) &&
567
+			!reflect.DeepEqual(request.Spec.Networks, service.Spec.Networks) &&
568
+			reflect.DeepEqual(request.Spec.Task.Networks, service.Spec.Task.Networks) {
573 569
 			return grpc.Errorf(codes.Unimplemented, errNetworkUpdateNotSupported.Error())
574 570
 		}
575 571
 
... ...
@@ -599,8 +599,11 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
599 599
 			}
600 600
 
601 601
 			curSpec := service.Spec.Copy()
602
+			curSpecVersion := service.SpecVersion
602 603
 			service.Spec = *service.PreviousSpec.Copy()
604
+			service.SpecVersion = service.PreviousSpecVersion.Copy()
603 605
 			service.PreviousSpec = curSpec
606
+			service.PreviousSpecVersion = curSpecVersion
604 607
 
605 608
 			service.UpdateStatus = &api.UpdateStatus{
606 609
 				State:     api.UpdateStatus_ROLLBACK_STARTED,
... ...
@@ -609,13 +612,19 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
609 609
 			}
610 610
 		} else {
611 611
 			service.PreviousSpec = service.Spec.Copy()
612
+			service.PreviousSpecVersion = service.SpecVersion
612 613
 			service.Spec = *request.Spec.Copy()
614
+			// Set spec version. Note that this will not match the
615
+			// service's Meta.Version after the store update. The
616
+			// versionsfor the spec and the service itself are not
617
+			// meant to be directly comparable.
618
+			service.SpecVersion = service.Meta.Version.Copy()
613 619
 
614 620
 			// Reset update status
615 621
 			service.UpdateStatus = nil
616 622
 		}
617 623
 
618
-		if doesServiceNeedIngress(service) {
624
+		if allocator.IsIngressNetworkNeeded(service) {
619 625
 			if _, err := allocator.GetIngressNetwork(s.store); err == allocator.ErrNoIngress {
620 626
 				return grpc.Errorf(codes.FailedPrecondition, "service needs ingress network, but no ingress network is present")
621 627
 			}
... ...
@@ -687,6 +696,8 @@ func (s *Server) ListServices(ctx context.Context, request *api.ListServicesRequ
687 687
 			services, err = store.FindServices(tx, buildFilters(store.ByNamePrefix, request.Filters.NamePrefixes))
688 688
 		case request.Filters != nil && len(request.Filters.IDPrefixes) > 0:
689 689
 			services, err = store.FindServices(tx, buildFilters(store.ByIDPrefix, request.Filters.IDPrefixes))
690
+		case request.Filters != nil && len(request.Filters.Runtimes) > 0:
691
+			services, err = store.FindServices(tx, buildFilters(store.ByRuntime, request.Filters.Runtimes))
690 692
 		default:
691 693
 			services, err = store.FindServices(tx, store.All)
692 694
 		}
... ...
@@ -709,6 +720,16 @@ func (s *Server) ListServices(ctx context.Context, request *api.ListServicesRequ
709 709
 			func(e *api.Service) bool {
710 710
 				return filterMatchLabels(e.Spec.Annotations.Labels, request.Filters.Labels)
711 711
 			},
712
+			func(e *api.Service) bool {
713
+				if len(request.Filters.Runtimes) == 0 {
714
+					return true
715
+				}
716
+				r, err := naming.Runtime(e.Spec.Task)
717
+				if err != nil {
718
+					return false
719
+				}
720
+				return filterContains(r, request.Filters.Runtimes)
721
+			},
712 722
 		)
713 723
 	}
714 724
 
... ...
@@ -87,6 +87,8 @@ func (s *Server) ListTasks(ctx context.Context, request *api.ListTasksRequest) (
87 87
 			tasks, err = store.FindTasks(tx, buildFilters(store.ByIDPrefix, request.Filters.IDPrefixes))
88 88
 		case request.Filters != nil && len(request.Filters.ServiceIDs) > 0:
89 89
 			tasks, err = store.FindTasks(tx, buildFilters(store.ByServiceID, request.Filters.ServiceIDs))
90
+		case request.Filters != nil && len(request.Filters.Runtimes) > 0:
91
+			tasks, err = store.FindTasks(tx, buildFilters(store.ByRuntime, request.Filters.Runtimes))
90 92
 		case request.Filters != nil && len(request.Filters.NodeIDs) > 0:
91 93
 			tasks, err = store.FindTasks(tx, buildFilters(store.ByNodeID, request.Filters.NodeIDs))
92 94
 		case request.Filters != nil && len(request.Filters.DesiredStates) > 0:
... ...
@@ -123,6 +125,16 @@ func (s *Server) ListTasks(ctx context.Context, request *api.ListTasksRequest) (
123 123
 				return filterContains(e.NodeID, request.Filters.NodeIDs)
124 124
 			},
125 125
 			func(e *api.Task) bool {
126
+				if len(request.Filters.Runtimes) == 0 {
127
+					return true
128
+				}
129
+				r, err := naming.Runtime(e.Spec)
130
+				if err != nil {
131
+					return false
132
+				}
133
+				return filterContains(r, request.Filters.Runtimes)
134
+			},
135
+			func(e *api.Task) bool {
126 136
 				if len(request.Filters.DesiredStates) == 0 {
127 137
 					return true
128 138
 				}
... ...
@@ -200,7 +200,7 @@ func (d *Dispatcher) Run(ctx context.Context) error {
200 200
 			}
201 201
 			return nil
202 202
 		},
203
-		state.EventUpdateCluster{},
203
+		api.EventUpdateCluster{},
204 204
 	)
205 205
 	if err != nil {
206 206
 		d.mu.Unlock()
... ...
@@ -249,7 +249,7 @@ func (d *Dispatcher) Run(ctx context.Context) error {
249 249
 			d.processUpdates(ctx)
250 250
 			batchTimer.Reset(maxBatchInterval)
251 251
 		case v := <-configWatcher:
252
-			cluster := v.(state.EventUpdateCluster)
252
+			cluster := v.(api.EventUpdateCluster)
253 253
 			d.mu.Lock()
254 254
 			if cluster.Cluster.Spec.Dispatcher.HeartbeatPeriod != nil {
255 255
 				// ignore error, since Spec has passed validation before
... ...
@@ -346,9 +346,9 @@ func (d *Dispatcher) markNodesUnknown(ctx context.Context) error {
346 346
 
347 347
 				expireFunc := func() {
348 348
 					log := log.WithField("node", nodeID)
349
-					log.Debugf("heartbeat expiration for unknown node")
349
+					log.Debug("heartbeat expiration for unknown node")
350 350
 					if err := d.markNodeNotReady(nodeID, api.NodeStatus_DOWN, `heartbeat failure for node in "unknown" state`); err != nil {
351
-						log.WithError(err).Errorf(`failed deregistering node after heartbeat expiration for node in "unknown" state`)
351
+						log.WithError(err).Error(`failed deregistering node after heartbeat expiration for node in "unknown" state`)
352 352
 					}
353 353
 				}
354 354
 				if err := d.nodes.AddUnknown(node, expireFunc); err != nil {
... ...
@@ -360,7 +360,7 @@ func (d *Dispatcher) markNodesUnknown(ctx context.Context) error {
360 360
 				return nil
361 361
 			})
362 362
 			if err != nil {
363
-				log.WithField("node", n.ID).WithError(err).Errorf(`failed to move node to "unknown" state`)
363
+				log.WithField("node", n.ID).WithError(err).Error(`failed to move node to "unknown" state`)
364 364
 			}
365 365
 		}
366 366
 		return nil
... ...
@@ -457,7 +457,7 @@ func (d *Dispatcher) register(ctx context.Context, nodeID string, description *a
457 457
 
458 458
 	addr, err := nodeIPFromContext(ctx)
459 459
 	if err != nil {
460
-		log.G(ctx).Debugf(err.Error())
460
+		log.G(ctx).Debug(err.Error())
461 461
 	}
462 462
 
463 463
 	if err := d.markNodeReady(dctx, nodeID, description, addr); err != nil {
... ...
@@ -701,12 +701,12 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe
701 701
 			}
702 702
 			return nil
703 703
 		},
704
-		state.EventCreateTask{Task: &api.Task{NodeID: nodeID},
705
-			Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}},
706
-		state.EventUpdateTask{Task: &api.Task{NodeID: nodeID},
707
-			Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}},
708
-		state.EventDeleteTask{Task: &api.Task{NodeID: nodeID},
709
-			Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}},
704
+		api.EventCreateTask{Task: &api.Task{NodeID: nodeID},
705
+			Checks: []api.TaskCheckFunc{state.TaskCheckNodeID}},
706
+		api.EventUpdateTask{Task: &api.Task{NodeID: nodeID},
707
+			Checks: []api.TaskCheckFunc{state.TaskCheckNodeID}},
708
+		api.EventDeleteTask{Task: &api.Task{NodeID: nodeID},
709
+			Checks: []api.TaskCheckFunc{state.TaskCheckNodeID}},
710 710
 	)
711 711
 	if err != nil {
712 712
 		return err
... ...
@@ -742,10 +742,10 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe
742 742
 			select {
743 743
 			case event := <-nodeTasks:
744 744
 				switch v := event.(type) {
745
-				case state.EventCreateTask:
745
+				case api.EventCreateTask:
746 746
 					tasksMap[v.Task.ID] = v.Task
747 747
 					modificationCnt++
748
-				case state.EventUpdateTask:
748
+				case api.EventUpdateTask:
749 749
 					if oldTask, exists := tasksMap[v.Task.ID]; exists {
750 750
 						// States ASSIGNED and below are set by the orchestrator/scheduler,
751 751
 						// not the agent, so tasks in these states need to be sent to the
... ...
@@ -758,7 +758,7 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe
758 758
 					}
759 759
 					tasksMap[v.Task.ID] = v.Task
760 760
 					modificationCnt++
761
-				case state.EventDeleteTask:
761
+				case api.EventDeleteTask:
762 762
 					delete(tasksMap, v.Task.ID)
763 763
 					modificationCnt++
764 764
 				}
... ...
@@ -915,12 +915,12 @@ func (d *Dispatcher) Assignments(r *api.AssignmentsRequest, stream api.Dispatche
915 915
 			}
916 916
 			return nil
917 917
 		},
918
-		state.EventUpdateTask{Task: &api.Task{NodeID: nodeID},
919
-			Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}},
920
-		state.EventDeleteTask{Task: &api.Task{NodeID: nodeID},
921
-			Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}},
922
-		state.EventUpdateSecret{},
923
-		state.EventDeleteSecret{},
918
+		api.EventUpdateTask{Task: &api.Task{NodeID: nodeID},
919
+			Checks: []api.TaskCheckFunc{state.TaskCheckNodeID}},
920
+		api.EventDeleteTask{Task: &api.Task{NodeID: nodeID},
921
+			Checks: []api.TaskCheckFunc{state.TaskCheckNodeID}},
922
+		api.EventUpdateSecret{},
923
+		api.EventDeleteSecret{},
924 924
 	)
925 925
 	if err != nil {
926 926
 		return err
... ...
@@ -996,7 +996,7 @@ func (d *Dispatcher) Assignments(r *api.AssignmentsRequest, stream api.Dispatche
996 996
 				// created by the orchestrator, then the scheduler moves
997 997
 				// them to ASSIGNED. If this ever changes, we will need
998 998
 				// to monitor task creations as well.
999
-				case state.EventUpdateTask:
999
+				case api.EventUpdateTask:
1000 1000
 					// We only care about tasks that are ASSIGNED or
1001 1001
 					// higher.
1002 1002
 					if v.Task.Status.State < api.TaskStateAssigned {
... ...
@@ -1038,7 +1038,7 @@ func (d *Dispatcher) Assignments(r *api.AssignmentsRequest, stream api.Dispatche
1038 1038
 					updateTasks[v.Task.ID] = v.Task
1039 1039
 
1040 1040
 					oneModification()
1041
-				case state.EventDeleteTask:
1041
+				case api.EventDeleteTask:
1042 1042
 					if _, exists := tasksMap[v.Task.ID]; !exists {
1043 1043
 						continue
1044 1044
 					}
... ...
@@ -1056,14 +1056,14 @@ func (d *Dispatcher) Assignments(r *api.AssignmentsRequest, stream api.Dispatche
1056 1056
 					oneModification()
1057 1057
 				// TODO(aaronl): For node secrets, we'll need to handle
1058 1058
 				// EventCreateSecret.
1059
-				case state.EventUpdateSecret:
1059
+				case api.EventUpdateSecret:
1060 1060
 					if _, exists := tasksUsingSecret[v.Secret.ID]; !exists {
1061 1061
 						continue
1062 1062
 					}
1063 1063
 					log.Debugf("Secret %s (ID: %d) was updated though it was still referenced by one or more tasks",
1064 1064
 						v.Secret.Spec.Annotations.Name, v.Secret.ID)
1065 1065
 
1066
-				case state.EventDeleteSecret:
1066
+				case api.EventDeleteSecret:
1067 1067
 					if _, exists := tasksUsingSecret[v.Secret.ID]; !exists {
1068 1068
 						continue
1069 1069
 					}
... ...
@@ -1171,7 +1171,16 @@ func (d *Dispatcher) moveTasksToOrphaned(nodeID string) error {
1171 1171
 		}
1172 1172
 
1173 1173
 		for _, task := range tasks {
1174
-			if task.Status.State < api.TaskStateOrphaned {
1174
+			// Tasks running on an unreachable node need to be marked as
1175
+			// orphaned since we have no idea whether the task is still running
1176
+			// or not.
1177
+			//
1178
+			// This only applies for tasks that could have made progress since
1179
+			// the agent became unreachable (assigned<->running)
1180
+			//
1181
+			// Tasks in a final state (e.g. rejected) *cannot* have made
1182
+			// progress, therefore there's no point in marking them as orphaned
1183
+			if task.Status.State >= api.TaskStateAssigned && task.Status.State <= api.TaskStateRunning {
1175 1184
 				task.Status.State = api.TaskStateOrphaned
1176 1185
 			}
1177 1186
 
... ...
@@ -1327,8 +1336,8 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
1327 1327
 	nodeUpdates, cancel, err := store.ViewAndWatch(d.store, func(readTx store.ReadTx) error {
1328 1328
 		nodeObj = store.GetNode(readTx, nodeID)
1329 1329
 		return nil
1330
-	}, state.EventUpdateNode{Node: &api.Node{ID: nodeID},
1331
-		Checks: []state.NodeCheckFunc{state.NodeCheckID}},
1330
+	}, api.EventUpdateNode{Node: &api.Node{ID: nodeID},
1331
+		Checks: []api.NodeCheckFunc{state.NodeCheckID}},
1332 1332
 	)
1333 1333
 	if cancel != nil {
1334 1334
 		defer cancel()
... ...
@@ -1394,7 +1403,7 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
1394 1394
 		case ev := <-managerUpdates:
1395 1395
 			mgrs = ev.([]*api.WeightedPeer)
1396 1396
 		case ev := <-nodeUpdates:
1397
-			nodeObj = ev.(state.EventUpdateNode).Node
1397
+			nodeObj = ev.(api.EventUpdateNode).Node
1398 1398
 		case <-stream.Context().Done():
1399 1399
 			return stream.Context().Err()
1400 1400
 		case <-node.Disconnect:
... ...
@@ -68,7 +68,7 @@ func (s *subscription) Run(ctx context.Context) {
68 68
 
69 69
 	if s.follow() {
70 70
 		wq := s.store.WatchQueue()
71
-		ch, cancel := state.Watch(wq, state.EventCreateTask{}, state.EventUpdateTask{})
71
+		ch, cancel := state.Watch(wq, api.EventCreateTask{}, api.EventUpdateTask{})
72 72
 		go func() {
73 73
 			defer cancel()
74 74
 			s.watch(ch)
... ...
@@ -227,9 +227,9 @@ func (s *subscription) watch(ch <-chan events.Event) error {
227 227
 			return s.ctx.Err()
228 228
 		case event := <-ch:
229 229
 			switch v := event.(type) {
230
-			case state.EventCreateTask:
230
+			case api.EventCreateTask:
231 231
 				t = v.Task
232
-			case state.EventUpdateTask:
232
+			case api.EventUpdateTask:
233 233
 				t = v.Task
234 234
 			}
235 235
 		}
... ...
@@ -389,7 +389,7 @@ func (m *Manager) Run(parent context.Context) error {
389 389
 		return err
390 390
 	}
391 391
 
392
-	baseControlAPI := controlapi.NewServer(m.raftNode.MemoryStore(), m.raftNode, m.config.SecurityConfig.RootCA(), m.config.PluginGetter)
392
+	baseControlAPI := controlapi.NewServer(m.raftNode.MemoryStore(), m.raftNode, m.config.SecurityConfig, m.caserver, m.config.PluginGetter)
393 393
 	baseResourceAPI := resourceapi.New(m.raftNode.MemoryStore())
394 394
 	healthServer := health.NewHealthServer()
395 395
 	localHealthServer := health.NewHealthServer()
... ...
@@ -688,12 +688,14 @@ func (m *Manager) watchForClusterChanges(ctx context.Context) error {
688 688
 			if cluster == nil {
689 689
 				return fmt.Errorf("unable to get current cluster")
690 690
 			}
691
-			m.caserver.UpdateRootCA(ctx, cluster)
691
+			if err := m.caserver.UpdateRootCA(ctx, cluster); err != nil {
692
+				log.G(ctx).WithError(err).Error("could not update security config")
693
+			}
692 694
 			return m.updateKEK(ctx, cluster)
693 695
 		},
694
-		state.EventUpdateCluster{
696
+		api.EventUpdateCluster{
695 697
 			Cluster: &api.Cluster{ID: clusterID},
696
-			Checks:  []state.ClusterCheckFunc{state.ClusterCheckID},
698
+			Checks:  []api.ClusterCheckFunc{state.ClusterCheckID},
697 699
 		},
698 700
 	)
699 701
 	if err != nil {
... ...
@@ -703,8 +705,10 @@ func (m *Manager) watchForClusterChanges(ctx context.Context) error {
703 703
 		for {
704 704
 			select {
705 705
 			case event := <-clusterWatch:
706
-				clusterEvent := event.(state.EventUpdateCluster)
707
-				m.caserver.UpdateRootCA(ctx, clusterEvent.Cluster)
706
+				clusterEvent := event.(api.EventUpdateCluster)
707
+				if err := m.caserver.UpdateRootCA(ctx, clusterEvent.Cluster); err != nil {
708
+					log.G(ctx).WithError(err).Error("could not update security config")
709
+				}
708 710
 				m.updateKEK(ctx, clusterEvent.Cluster)
709 711
 			case <-ctx.Done():
710 712
 				clusterWatchCancel()
... ...
@@ -724,10 +728,15 @@ func (m *Manager) watchForClusterChanges(ctx context.Context) error {
724 724
 func (m *Manager) rotateRootCAKEK(ctx context.Context, clusterID string) error {
725 725
 	// If we don't have a KEK, we won't ever be rotating anything
726 726
 	strPassphrase := os.Getenv(ca.PassphraseENVVar)
727
-	if strPassphrase == "" {
727
+	strPassphrasePrev := os.Getenv(ca.PassphraseENVVarPrev)
728
+	if strPassphrase == "" && strPassphrasePrev == "" {
728 729
 		return nil
729 730
 	}
730
-	strPassphrasePrev := os.Getenv(ca.PassphraseENVVarPrev)
731
+	if strPassphrase != "" {
732
+		log.G(ctx).Warn("Encrypting the root CA key in swarm using environment variables is deprecated. " +
733
+			"Support for decrypting or rotating the key will be removed in the future.")
734
+	}
735
+
731 736
 	passphrase := []byte(strPassphrase)
732 737
 	passphrasePrev := []byte(strPassphrasePrev)
733 738
 
... ...
@@ -738,72 +747,72 @@ func (m *Manager) rotateRootCAKEK(ctx context.Context, clusterID string) error {
738 738
 		finalKey []byte
739 739
 	)
740 740
 	// Retrieve the cluster identified by ClusterID
741
-	s.View(func(readTx store.ReadTx) {
742
-		cluster = store.GetCluster(readTx, clusterID)
743
-	})
744
-	if cluster == nil {
745
-		return fmt.Errorf("cluster not found: %s", clusterID)
746
-	}
747
-
748
-	// Try to get the private key from the cluster
749
-	privKeyPEM := cluster.RootCA.CAKey
750
-	if len(privKeyPEM) == 0 {
751
-		// We have no PEM root private key in this cluster.
752
-		log.G(ctx).Warnf("cluster %s does not have private key material", clusterID)
753
-		return nil
754
-	}
755
-
756
-	// Decode the PEM private key
757
-	keyBlock, _ := pem.Decode(privKeyPEM)
758
-	if keyBlock == nil {
759
-		return fmt.Errorf("invalid PEM-encoded private key inside of cluster %s", clusterID)
760
-	}
761
-	// If this key is not encrypted, then we have to encrypt it
762
-	if !x509.IsEncryptedPEMBlock(keyBlock) {
763
-		finalKey, err = ca.EncryptECPrivateKey(privKeyPEM, strPassphrase)
764
-		if err != nil {
765
-			return err
741
+	return s.Update(func(tx store.Tx) error {
742
+		cluster = store.GetCluster(tx, clusterID)
743
+		if cluster == nil {
744
+			return fmt.Errorf("cluster not found: %s", clusterID)
766 745
 		}
767
-	} else {
768
-		// This key is already encrypted, let's try to decrypt with the current main passphrase
769
-		_, err = x509.DecryptPEMBlock(keyBlock, []byte(passphrase))
770
-		if err == nil {
771
-			// The main key is the correct KEK, nothing to do here
746
+
747
+		// Try to get the private key from the cluster
748
+		privKeyPEM := cluster.RootCA.CAKey
749
+		if len(privKeyPEM) == 0 {
750
+			// We have no PEM root private key in this cluster.
751
+			log.G(ctx).Warnf("cluster %s does not have private key material", clusterID)
772 752
 			return nil
773 753
 		}
774
-		// This key is already encrypted, but failed with current main passphrase.
775
-		// Let's try to decrypt with the previous passphrase
776
-		unencryptedKey, err := x509.DecryptPEMBlock(keyBlock, []byte(passphrasePrev))
777
-		if err != nil {
778
-			// We were not able to decrypt either with the main or backup passphrase, error
779
-			return err
780
-		}
781
-		unencryptedKeyBlock := &pem.Block{
782
-			Type:    keyBlock.Type,
783
-			Bytes:   unencryptedKey,
784
-			Headers: keyBlock.Headers,
785
-		}
786 754
 
787
-		// We were able to decrypt the key, but with the previous passphrase. Let's encrypt
788
-		// with the new one and store it in raft
789
-		finalKey, err = ca.EncryptECPrivateKey(pem.EncodeToMemory(unencryptedKeyBlock), strPassphrase)
790
-		if err != nil {
791
-			log.G(ctx).Debugf("failed to rotate the key-encrypting-key for the root key material of cluster %s", clusterID)
792
-			return err
755
+		// Decode the PEM private key
756
+		keyBlock, _ := pem.Decode(privKeyPEM)
757
+		if keyBlock == nil {
758
+			return fmt.Errorf("invalid PEM-encoded private key inside of cluster %s", clusterID)
793 759
 		}
794
-	}
795 760
 
796
-	log.G(ctx).Infof("Re-encrypting the root key material of cluster %s", clusterID)
797
-	// Let's update the key in the cluster object
798
-	return s.Update(func(tx store.Tx) error {
799
-		cluster = store.GetCluster(tx, clusterID)
800
-		if cluster == nil {
801
-			return fmt.Errorf("cluster not found: %s", clusterID)
761
+		if x509.IsEncryptedPEMBlock(keyBlock) {
762
+			// This key is already encrypted, let's try to decrypt with the current main passphrase
763
+			_, err = x509.DecryptPEMBlock(keyBlock, []byte(passphrase))
764
+			if err == nil {
765
+				// The main key is the correct KEK, nothing to do here
766
+				return nil
767
+			}
768
+			// This key is already encrypted, but failed with current main passphrase.
769
+			// Let's try to decrypt with the previous passphrase
770
+			unencryptedKey, err := x509.DecryptPEMBlock(keyBlock, []byte(passphrasePrev))
771
+			if err != nil {
772
+				// We were not able to decrypt either with the main or backup passphrase, error
773
+				return err
774
+			}
775
+			unencryptedKeyBlock := &pem.Block{
776
+				Type:  keyBlock.Type,
777
+				Bytes: unencryptedKey,
778
+			}
779
+
780
+			// we were able to decrypt the key with the previous passphrase - if the current passphrase is empty,
781
+			// the we store the decrypted key in raft
782
+			finalKey = pem.EncodeToMemory(unencryptedKeyBlock)
783
+
784
+			// the current passphrase is not empty, so let's encrypt with the new one and store it in raft
785
+			if strPassphrase != "" {
786
+				finalKey, err = ca.EncryptECPrivateKey(finalKey, strPassphrase)
787
+				if err != nil {
788
+					log.G(ctx).WithError(err).Debugf("failed to rotate the key-encrypting-key for the root key material of cluster %s", clusterID)
789
+					return err
790
+				}
791
+			}
792
+		} else if strPassphrase != "" {
793
+			// If this key is not encrypted, and the passphrase is not nil, then we have to encrypt it
794
+			finalKey, err = ca.EncryptECPrivateKey(privKeyPEM, strPassphrase)
795
+			if err != nil {
796
+				log.G(ctx).WithError(err).Debugf("failed to rotate the key-encrypting-key for the root key material of cluster %s", clusterID)
797
+				return err
798
+			}
799
+		} else {
800
+			return nil // don't update if it's not encrypted and we don't want it encrypted
802 801
 		}
802
+
803
+		log.G(ctx).Infof("Updating the encryption on the root key material of cluster %s", clusterID)
803 804
 		cluster.RootCA.CAKey = finalKey
804 805
 		return store.UpdateCluster(tx, cluster)
805 806
 	})
806
-
807 807
 }
808 808
 
809 809
 // handleLeadershipEvents handles the is leader event or is follower event.
... ...
@@ -1045,8 +1054,8 @@ func defaultClusterObject(
1045 1045
 	initialUnlockKeys []*api.EncryptionKey,
1046 1046
 	rootCA *ca.RootCA) *api.Cluster {
1047 1047
 	var caKey []byte
1048
-	if rootCA.Signer != nil {
1049
-		caKey = rootCA.Signer.Key
1048
+	if rcaSigner, err := rootCA.Signer(); err == nil {
1049
+		caKey = rcaSigner.Key
1050 1050
 	}
1051 1051
 
1052 1052
 	return &api.Cluster{
... ...
@@ -1067,7 +1076,7 @@ func defaultClusterObject(
1067 1067
 		},
1068 1068
 		RootCA: api.RootCA{
1069 1069
 			CAKey:      caKey,
1070
-			CACert:     rootCA.Cert,
1070
+			CACert:     rootCA.Certs,
1071 1071
 			CACertHash: rootCA.Digest.String(),
1072 1072
 			JoinTokens: api.JoinTokens{
1073 1073
 				Worker:  ca.GenerateJoinToken(rootCA),
... ...
@@ -32,7 +32,7 @@ func New(store *store.MemoryStore) *ConstraintEnforcer {
32 32
 func (ce *ConstraintEnforcer) Run() {
33 33
 	defer close(ce.doneChan)
34 34
 
35
-	watcher, cancelWatch := state.Watch(ce.store.WatchQueue(), state.EventUpdateNode{})
35
+	watcher, cancelWatch := state.Watch(ce.store.WatchQueue(), api.EventUpdateNode{})
36 36
 	defer cancelWatch()
37 37
 
38 38
 	var (
... ...
@@ -53,7 +53,7 @@ func (ce *ConstraintEnforcer) Run() {
53 53
 	for {
54 54
 		select {
55 55
 		case event := <-watcher:
56
-			node := event.(state.EventUpdateNode).Node
56
+			node := event.(api.EventUpdateNode).Node
57 57
 			ce.rejectNoncompliantTasks(node)
58 58
 		case <-ce.stopChan:
59 59
 			return
... ...
@@ -8,7 +8,6 @@ import (
8 8
 	"github.com/docker/swarmkit/manager/orchestrator/restart"
9 9
 	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
10 10
 	"github.com/docker/swarmkit/manager/orchestrator/update"
11
-	"github.com/docker/swarmkit/manager/state"
12 11
 	"github.com/docker/swarmkit/manager/state/store"
13 12
 	"golang.org/x/net/context"
14 13
 )
... ...
@@ -130,21 +129,21 @@ func (g *Orchestrator) Run(ctx context.Context) error {
130 130
 		case event := <-watcher:
131 131
 			// TODO(stevvooe): Use ctx to limit running time of operation.
132 132
 			switch v := event.(type) {
133
-			case state.EventUpdateCluster:
133
+			case api.EventUpdateCluster:
134 134
 				g.cluster = v.Cluster
135
-			case state.EventCreateService:
135
+			case api.EventCreateService:
136 136
 				if !orchestrator.IsGlobalService(v.Service) {
137 137
 					continue
138 138
 				}
139 139
 				g.updateService(v.Service)
140 140
 				g.reconcileServices(ctx, []string{v.Service.ID})
141
-			case state.EventUpdateService:
141
+			case api.EventUpdateService:
142 142
 				if !orchestrator.IsGlobalService(v.Service) {
143 143
 					continue
144 144
 				}
145 145
 				g.updateService(v.Service)
146 146
 				g.reconcileServices(ctx, []string{v.Service.ID})
147
-			case state.EventDeleteService:
147
+			case api.EventDeleteService:
148 148
 				if !orchestrator.IsGlobalService(v.Service) {
149 149
 					continue
150 150
 				}
... ...
@@ -152,10 +151,10 @@ func (g *Orchestrator) Run(ctx context.Context) error {
152 152
 				// delete the service from service map
153 153
 				delete(g.globalServices, v.Service.ID)
154 154
 				g.restarts.ClearServiceHistory(v.Service.ID)
155
-			case state.EventCreateNode:
155
+			case api.EventCreateNode:
156 156
 				g.updateNode(v.Node)
157 157
 				g.reconcileOneNode(ctx, v.Node)
158
-			case state.EventUpdateNode:
158
+			case api.EventUpdateNode:
159 159
 				g.updateNode(v.Node)
160 160
 				switch v.Node.Status.State {
161 161
 				// NodeStatus_DISCONNECTED is a transient state, no need to make any change
... ...
@@ -165,12 +164,12 @@ func (g *Orchestrator) Run(ctx context.Context) error {
165 165
 					// node could come back to READY from DOWN or DISCONNECT
166 166
 					g.reconcileOneNode(ctx, v.Node)
167 167
 				}
168
-			case state.EventDeleteNode:
168
+			case api.EventDeleteNode:
169 169
 				g.removeTasksFromNode(ctx, v.Node)
170 170
 				delete(g.nodes, v.Node.ID)
171
-			case state.EventUpdateTask:
171
+			case api.EventUpdateTask:
172 172
 				g.handleTaskChange(ctx, v.Task)
173
-			case state.EventDeleteTask:
173
+			case api.EventDeleteTask:
174 174
 				// CLI allows deleting task
175 175
 				if _, exists := g.globalServices[v.Task.ServiceID]; !exists {
176 176
 					continue
... ...
@@ -83,7 +83,7 @@ func (r *Orchestrator) Run(ctx context.Context) error {
83 83
 			switch v := event.(type) {
84 84
 			case state.EventCommit:
85 85
 				r.tick(ctx)
86
-			case state.EventUpdateCluster:
86
+			case api.EventUpdateCluster:
87 87
 				r.cluster = v.Cluster
88 88
 			}
89 89
 		case <-r.stopChan:
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"github.com/docker/swarmkit/api"
8 8
 	"github.com/docker/swarmkit/log"
9 9
 	"github.com/docker/swarmkit/manager/orchestrator"
10
-	"github.com/docker/swarmkit/manager/state"
11 10
 	"github.com/docker/swarmkit/manager/state/store"
12 11
 	"golang.org/x/net/context"
13 12
 )
... ...
@@ -47,19 +46,19 @@ func (r *Orchestrator) initServices(readTx store.ReadTx) error {
47 47
 
48 48
 func (r *Orchestrator) handleServiceEvent(ctx context.Context, event events.Event) {
49 49
 	switch v := event.(type) {
50
-	case state.EventDeleteService:
50
+	case api.EventDeleteService:
51 51
 		if !orchestrator.IsReplicatedService(v.Service) {
52 52
 			return
53 53
 		}
54 54
 		orchestrator.DeleteServiceTasks(ctx, r.store, v.Service)
55 55
 		r.restarts.ClearServiceHistory(v.Service.ID)
56 56
 		delete(r.reconcileServices, v.Service.ID)
57
-	case state.EventCreateService:
57
+	case api.EventCreateService:
58 58
 		if !orchestrator.IsReplicatedService(v.Service) {
59 59
 			return
60 60
 		}
61 61
 		r.reconcileServices[v.Service.ID] = v.Service
62
-	case state.EventUpdateService:
62
+	case api.EventUpdateService:
63 63
 		if !orchestrator.IsReplicatedService(v.Service) {
64 64
 			return
65 65
 		}
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"github.com/docker/swarmkit/log"
7 7
 	"github.com/docker/swarmkit/manager/orchestrator"
8 8
 	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
9
-	"github.com/docker/swarmkit/manager/state"
10 9
 	"github.com/docker/swarmkit/manager/state/store"
11 10
 	"golang.org/x/net/context"
12 11
 )
... ...
@@ -22,13 +21,13 @@ func (r *Orchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error
22 22
 
23 23
 func (r *Orchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
24 24
 	switch v := event.(type) {
25
-	case state.EventDeleteNode:
25
+	case api.EventDeleteNode:
26 26
 		r.restartTasksByNodeID(ctx, v.Node.ID)
27
-	case state.EventCreateNode:
27
+	case api.EventCreateNode:
28 28
 		r.handleNodeChange(ctx, v.Node)
29
-	case state.EventUpdateNode:
29
+	case api.EventUpdateNode:
30 30
 		r.handleNodeChange(ctx, v.Node)
31
-	case state.EventDeleteTask:
31
+	case api.EventDeleteTask:
32 32
 		if v.Task.DesiredState <= api.TaskStateRunning {
33 33
 			service := r.resolveService(ctx, v.Task)
34 34
 			if !orchestrator.IsReplicatedService(service) {
... ...
@@ -37,9 +36,9 @@ func (r *Orchestrator) handleTaskEvent(ctx context.Context, event events.Event)
37 37
 			r.reconcileServices[service.ID] = service
38 38
 		}
39 39
 		r.restarts.Cancel(v.Task.ID)
40
-	case state.EventUpdateTask:
40
+	case api.EventUpdateTask:
41 41
 		r.handleTaskChange(ctx, v.Task)
42
-	case state.EventCreateTask:
42
+	case api.EventCreateTask:
43 43
 		r.handleTaskChange(ctx, v.Task)
44 44
 	}
45 45
 }
... ...
@@ -327,17 +327,17 @@ func (r *Supervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask *api.Ta
327 327
 		// node to become unavailable.
328 328
 		watch, cancelWatch = state.Watch(
329 329
 			r.store.WatchQueue(),
330
-			state.EventUpdateTask{
330
+			api.EventUpdateTask{
331 331
 				Task:   &api.Task{ID: oldTask.ID, Status: api.TaskStatus{State: api.TaskStateRunning}},
332
-				Checks: []state.TaskCheckFunc{state.TaskCheckID, state.TaskCheckStateGreaterThan},
332
+				Checks: []api.TaskCheckFunc{state.TaskCheckID, state.TaskCheckStateGreaterThan},
333 333
 			},
334
-			state.EventUpdateNode{
334
+			api.EventUpdateNode{
335 335
 				Node:   &api.Node{ID: oldTask.NodeID, Status: api.NodeStatus{State: api.NodeStatus_DOWN}},
336
-				Checks: []state.NodeCheckFunc{state.NodeCheckID, state.NodeCheckState},
336
+				Checks: []api.NodeCheckFunc{state.NodeCheckID, state.NodeCheckState},
337 337
 			},
338
-			state.EventDeleteNode{
338
+			api.EventDeleteNode{
339 339
 				Node:   &api.Node{ID: oldTask.NodeID},
340
-				Checks: []state.NodeCheckFunc{state.NodeCheckID},
340
+				Checks: []api.NodeCheckFunc{state.NodeCheckID},
341 341
 			},
342 342
 		)
343 343
 	}
... ...
@@ -29,6 +29,7 @@ func NewTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID str
29 29
 		ID:                 taskID,
30 30
 		ServiceAnnotations: service.Spec.Annotations,
31 31
 		Spec:               service.Spec.Task,
32
+		SpecVersion:        service.SpecVersion,
32 33
 		ServiceID:          service.ID,
33 34
 		Slot:               slot,
34 35
 		Status: api.TaskStatus{
... ...
@@ -62,6 +63,13 @@ func RestartCondition(task *api.Task) api.RestartPolicy_RestartCondition {
62 62
 
63 63
 // IsTaskDirty determines whether a task matches the given service's spec.
64 64
 func IsTaskDirty(s *api.Service, t *api.Task) bool {
65
+	// If the spec version matches, we know the task is not dirty. However,
66
+	// if it does not match, that doesn't mean the task is dirty, since
67
+	// only a portion of the spec is included in the comparison.
68
+	if t.SpecVersion != nil && *s.SpecVersion == *t.SpecVersion {
69
+		return false
70
+	}
71
+
65 72
 	return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
66 73
 		(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
67 74
 }
... ...
@@ -41,7 +41,7 @@ type TaskReaper struct {
41 41
 
42 42
 // New creates a new TaskReaper.
43 43
 func New(store *store.MemoryStore) *TaskReaper {
44
-	watcher, cancel := state.Watch(store.WatchQueue(), state.EventCreateTask{}, state.EventUpdateTask{}, state.EventUpdateCluster{})
44
+	watcher, cancel := state.Watch(store.WatchQueue(), api.EventCreateTask{}, api.EventUpdateTask{}, api.EventUpdateCluster{})
45 45
 
46 46
 	return &TaskReaper{
47 47
 		store:       store,
... ...
@@ -93,19 +93,19 @@ func (tr *TaskReaper) Run() {
93 93
 		select {
94 94
 		case event := <-tr.watcher:
95 95
 			switch v := event.(type) {
96
-			case state.EventCreateTask:
96
+			case api.EventCreateTask:
97 97
 				t := v.Task
98 98
 				tr.dirty[instanceTuple{
99 99
 					instance:  t.Slot,
100 100
 					serviceID: t.ServiceID,
101 101
 					nodeID:    t.NodeID,
102 102
 				}] = struct{}{}
103
-			case state.EventUpdateTask:
103
+			case api.EventUpdateTask:
104 104
 				t := v.Task
105 105
 				if t.Status.State >= api.TaskStateOrphaned && t.ServiceID == "" {
106 106
 					tr.orphaned = append(tr.orphaned, t.ID)
107 107
 				}
108
-			case state.EventUpdateCluster:
108
+			case api.EventUpdateCluster:
109 109
 				tr.taskHistory = v.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
110 110
 			}
111 111
 
... ...
@@ -162,6 +162,7 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
162 162
 		failureAction          = api.UpdateConfig_PAUSE
163 163
 		allowedFailureFraction = float32(0)
164 164
 		monitoringPeriod       = defaultMonitor
165
+		order                  = api.UpdateConfig_STOP_FIRST
165 166
 	)
166 167
 
167 168
 	updateConfig := service.Spec.Update
... ...
@@ -174,6 +175,7 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
174 174
 		allowedFailureFraction = updateConfig.MaxFailureRatio
175 175
 		parallelism = int(updateConfig.Parallelism)
176 176
 		delay = updateConfig.Delay
177
+		order = updateConfig.Order
177 178
 
178 179
 		var err error
179 180
 		if updateConfig.Monitor != nil {
... ...
@@ -196,7 +198,7 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
196 196
 	wg.Add(parallelism)
197 197
 	for i := 0; i < parallelism; i++ {
198 198
 		go func() {
199
-			u.worker(ctx, slotQueue, delay)
199
+			u.worker(ctx, slotQueue, delay, order)
200 200
 			wg.Done()
201 201
 		}()
202 202
 	}
... ...
@@ -207,9 +209,9 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
207 207
 		var cancelWatch func()
208 208
 		failedTaskWatch, cancelWatch = state.Watch(
209 209
 			u.store.WatchQueue(),
210
-			state.EventUpdateTask{
210
+			api.EventUpdateTask{
211 211
 				Task:   &api.Task{ServiceID: service.ID, Status: api.TaskStatus{State: api.TaskStateRunning}},
212
-				Checks: []state.TaskCheckFunc{state.TaskCheckServiceID, state.TaskCheckStateGreaterThan},
212
+				Checks: []api.TaskCheckFunc{state.TaskCheckServiceID, state.TaskCheckStateGreaterThan},
213 213
 			},
214 214
 		)
215 215
 		defer cancelWatch()
... ...
@@ -270,7 +272,7 @@ slotsLoop:
270 270
 				stopped = true
271 271
 				break slotsLoop
272 272
 			case ev := <-failedTaskWatch:
273
-				if failureTriggersAction(ev.(state.EventUpdateTask).Task) {
273
+				if failureTriggersAction(ev.(api.EventUpdateTask).Task) {
274 274
 					break slotsLoop
275 275
 				}
276 276
 			case slotQueue <- slot:
... ...
@@ -295,7 +297,7 @@ slotsLoop:
295 295
 			case <-doneMonitoring:
296 296
 				break monitorLoop
297 297
 			case ev := <-failedTaskWatch:
298
-				if failureTriggersAction(ev.(state.EventUpdateTask).Task) {
298
+				if failureTriggersAction(ev.(api.EventUpdateTask).Task) {
299 299
 					break monitorLoop
300 300
 				}
301 301
 			}
... ...
@@ -310,7 +312,7 @@ slotsLoop:
310 310
 	}
311 311
 }
312 312
 
313
-func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot, delay time.Duration) {
313
+func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot, delay time.Duration, order api.UpdateConfig_UpdateOrder) {
314 314
 	for slot := range queue {
315 315
 		// Do we have a task with the new spec in desired state = RUNNING?
316 316
 		// If so, all we have to do to complete the update is remove the
... ...
@@ -347,7 +349,7 @@ func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot, de
347 347
 			}
348 348
 			updated.DesiredState = api.TaskStateReady
349 349
 
350
-			if err := u.updateTask(ctx, slot, updated); err != nil {
350
+			if err := u.updateTask(ctx, slot, updated, order); err != nil {
351 351
 				log.G(ctx).WithError(err).WithField("task.id", updated.ID).Error("update failed")
352 352
 			}
353 353
 		}
... ...
@@ -362,11 +364,11 @@ func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot, de
362 362
 	}
363 363
 }
364 364
 
365
-func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, updated *api.Task) error {
365
+func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, updated *api.Task, order api.UpdateConfig_UpdateOrder) error {
366 366
 	// Kick off the watch before even creating the updated task. This is in order to avoid missing any event.
367
-	taskUpdates, cancel := state.Watch(u.watchQueue, state.EventUpdateTask{
367
+	taskUpdates, cancel := state.Watch(u.watchQueue, api.EventUpdateTask{
368 368
 		Task:   &api.Task{ID: updated.ID},
369
-		Checks: []state.TaskCheckFunc{state.TaskCheckID},
369
+		Checks: []api.TaskCheckFunc{state.TaskCheckID},
370 370
 	})
371 371
 	defer cancel()
372 372
 
... ...
@@ -377,15 +379,11 @@ func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, update
377 377
 	u.updatedTasks[updated.ID] = time.Time{}
378 378
 	u.updatedTasksMu.Unlock()
379 379
 
380
+	startThenStop := false
380 381
 	var delayStartCh <-chan struct{}
381 382
 	// Atomically create the updated task and bring down the old one.
382 383
 	_, err := u.store.Batch(func(batch *store.Batch) error {
383
-		oldTask, err := u.removeOldTasks(ctx, batch, slot)
384
-		if err != nil {
385
-			return err
386
-		}
387
-
388
-		err = batch.Update(func(tx store.Tx) error {
384
+		err := batch.Update(func(tx store.Tx) error {
389 385
 			if store.GetService(tx, updated.ServiceID) == nil {
390 386
 				return errors.New("service was deleted")
391 387
 			}
... ...
@@ -399,7 +397,16 @@ func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, update
399 399
 			return err
400 400
 		}
401 401
 
402
-		delayStartCh = u.restarts.DelayStart(ctx, nil, oldTask, updated.ID, 0, true)
402
+		if order == api.UpdateConfig_START_FIRST {
403
+			delayStartCh = u.restarts.DelayStart(ctx, nil, nil, updated.ID, 0, false)
404
+			startThenStop = true
405
+		} else {
406
+			oldTask, err := u.removeOldTasks(ctx, batch, slot)
407
+			if err != nil {
408
+				return err
409
+			}
410
+			delayStartCh = u.restarts.DelayStart(ctx, nil, oldTask, updated.ID, 0, true)
411
+		}
403 412
 
404 413
 		return nil
405 414
 
... ...
@@ -421,11 +428,22 @@ func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, update
421 421
 	for {
422 422
 		select {
423 423
 		case e := <-taskUpdates:
424
-			updated = e.(state.EventUpdateTask).Task
424
+			updated = e.(api.EventUpdateTask).Task
425 425
 			if updated.Status.State >= api.TaskStateRunning {
426 426
 				u.updatedTasksMu.Lock()
427 427
 				u.updatedTasks[updated.ID] = time.Now()
428 428
 				u.updatedTasksMu.Unlock()
429
+
430
+				if startThenStop {
431
+					_, err := u.store.Batch(func(batch *store.Batch) error {
432
+						_, err := u.removeOldTasks(ctx, batch, slot)
433
+						if err != nil {
434
+							log.G(ctx).WithError(err).WithField("task.id", updated.ID).Warning("failed to remove old task after starting replacement")
435
+						}
436
+						return nil
437
+					})
438
+					return err
439
+				}
429 440
 				return nil
430 441
 			}
431 442
 		case <-u.stopChan:
... ...
@@ -5,7 +5,6 @@ import (
5 5
 
6 6
 	"github.com/docker/swarmkit/api"
7 7
 	"github.com/docker/swarmkit/log"
8
-	"github.com/docker/swarmkit/manager/state"
9 8
 	"github.com/docker/swarmkit/manager/state/raft"
10 9
 	"github.com/docker/swarmkit/manager/state/store"
11 10
 	"golang.org/x/net/context"
... ...
@@ -57,7 +56,7 @@ func (rm *roleManager) Run(ctx context.Context) {
57 57
 			nodes, err = store.FindNodes(readTx, store.All)
58 58
 			return err
59 59
 		},
60
-		state.EventUpdateNode{})
60
+		api.EventUpdateNode{})
61 61
 	defer cancelWatch()
62 62
 
63 63
 	if err != nil {
... ...
@@ -76,7 +75,7 @@ func (rm *roleManager) Run(ctx context.Context) {
76 76
 	for {
77 77
 		select {
78 78
 		case event := <-watcher:
79
-			node := event.(state.EventUpdateNode).Node
79
+			node := event.(api.EventUpdateNode).Node
80 80
 			rm.pending[node.ID] = node
81 81
 			rm.reconcileRole(ctx, node)
82 82
 			if len(rm.pending) != 0 && ticker == nil {
... ...
@@ -142,19 +142,19 @@ func (s *Scheduler) Run(ctx context.Context) error {
142 142
 		select {
143 143
 		case event := <-updates:
144 144
 			switch v := event.(type) {
145
-			case state.EventCreateTask:
145
+			case api.EventCreateTask:
146 146
 				pendingChanges += s.createTask(ctx, v.Task)
147
-			case state.EventUpdateTask:
147
+			case api.EventUpdateTask:
148 148
 				pendingChanges += s.updateTask(ctx, v.Task)
149
-			case state.EventDeleteTask:
149
+			case api.EventDeleteTask:
150 150
 				s.deleteTask(ctx, v.Task)
151
-			case state.EventCreateNode:
151
+			case api.EventCreateNode:
152 152
 				s.createOrUpdateNode(v.Node)
153 153
 				pendingChanges++
154
-			case state.EventUpdateNode:
154
+			case api.EventUpdateNode:
155 155
 				s.createOrUpdateNode(v.Node)
156 156
 				pendingChanges++
157
-			case state.EventDeleteNode:
157
+			case api.EventDeleteNode:
158 158
 				s.nodeSet.remove(v.Node.ID)
159 159
 			case state.EventCommit:
160 160
 				if commitDebounceTimer != nil {
... ...
@@ -331,7 +331,12 @@ func (s *Scheduler) processPreassignedTasks(ctx context.Context) {
331 331
 
332 332
 // tick attempts to schedule the queue.
333 333
 func (s *Scheduler) tick(ctx context.Context) {
334
-	tasksByCommonSpec := make(map[string]map[string]*api.Task)
334
+	type commonSpecKey struct {
335
+		serviceID   string
336
+		specVersion api.Version
337
+	}
338
+	tasksByCommonSpec := make(map[commonSpecKey]map[string]*api.Task)
339
+	var oneOffTasks []*api.Task
335 340
 	schedulingDecisions := make(map[string]schedulingDecision, len(s.unassignedTasks))
336 341
 
337 342
 	for taskID, t := range s.unassignedTasks {
... ...
@@ -341,30 +346,31 @@ func (s *Scheduler) tick(ctx context.Context) {
341 341
 			continue
342 342
 		}
343 343
 
344
-		// Group common tasks with common specs by marshalling the spec
345
-		// into taskKey and using it as a map key.
346
-		// TODO(aaronl): Once specs are versioned, this will allow a
347
-		// much more efficient fast path.
348
-		fieldsToMarshal := api.Task{
349
-			ServiceID: t.ServiceID,
350
-			Spec:      t.Spec,
351
-		}
352
-		marshalled, err := fieldsToMarshal.Marshal()
353
-		if err != nil {
354
-			panic(err)
355
-		}
356
-		taskGroupKey := string(marshalled)
344
+		// Group tasks with common specs
345
+		if t.SpecVersion != nil {
346
+			taskGroupKey := commonSpecKey{
347
+				serviceID:   t.ServiceID,
348
+				specVersion: *t.SpecVersion,
349
+			}
357 350
 
358
-		if tasksByCommonSpec[taskGroupKey] == nil {
359
-			tasksByCommonSpec[taskGroupKey] = make(map[string]*api.Task)
351
+			if tasksByCommonSpec[taskGroupKey] == nil {
352
+				tasksByCommonSpec[taskGroupKey] = make(map[string]*api.Task)
353
+			}
354
+			tasksByCommonSpec[taskGroupKey][taskID] = t
355
+		} else {
356
+			// This task doesn't have a spec version. We have to
357
+			// schedule it as a one-off.
358
+			oneOffTasks = append(oneOffTasks, t)
360 359
 		}
361
-		tasksByCommonSpec[taskGroupKey][taskID] = t
362 360
 		delete(s.unassignedTasks, taskID)
363 361
 	}
364 362
 
365 363
 	for _, taskGroup := range tasksByCommonSpec {
366 364
 		s.scheduleTaskGroup(ctx, taskGroup, schedulingDecisions)
367 365
 	}
366
+	for _, t := range oneOffTasks {
367
+		s.scheduleTaskGroup(ctx, map[string]*api.Task{t.ID: t}, schedulingDecisions)
368
+	}
368 369
 
369 370
 	_, failed := s.applySchedulingDecisions(ctx, schedulingDecisions)
370 371
 	for _, decision := range failed {
... ...
@@ -12,6 +12,6 @@ type Proposer interface {
12 12
 	// proposed changes. The callback is necessary for the Proposer to make
13 13
 	// sure that the changes are committed before it interacts further
14 14
 	// with the store.
15
-	ProposeValue(ctx context.Context, storeAction []*api.StoreAction, cb func()) error
15
+	ProposeValue(ctx context.Context, storeAction []api.StoreAction, cb func()) error
16 16
 	GetVersion() *api.Version
17 17
 }
... ...
@@ -1411,7 +1411,7 @@ func (n *Node) registerNode(node *api.RaftMember) error {
1411 1411
 
1412 1412
 // ProposeValue calls Propose on the raft and waits
1413 1413
 // on the commit log action before returning a result
1414
-func (n *Node) ProposeValue(ctx context.Context, storeAction []*api.StoreAction, cb func()) error {
1414
+func (n *Node) ProposeValue(ctx context.Context, storeAction []api.StoreAction, cb func()) error {
1415 1415
 	ctx, cancel := n.WithContext(ctx)
1416 1416
 	defer cancel()
1417 1417
 	_, err := n.processInternalRaftRequest(ctx, &api.InternalRaftRequest{Action: storeAction}, cb)
... ...
@@ -1663,10 +1663,6 @@ func (n *Node) processEntry(ctx context.Context, entry raftpb.Entry) error {
1663 1663
 		return err
1664 1664
 	}
1665 1665
 
1666
-	if r.Action == nil {
1667
-		return nil
1668
-	}
1669
-
1670 1666
 	if !n.wait.trigger(r.ID, r) {
1671 1667
 		// There was no wait on this ID, meaning we don't have a
1672 1668
 		// transaction in progress that would be committed to the
... ...
@@ -59,7 +59,7 @@ func WaitForLeader(ctx context.Context, n *Node) error {
59 59
 // committed to raft. This ensures that we can see and serve informations
60 60
 // related to the cluster.
61 61
 func WaitForCluster(ctx context.Context, n *Node) (cluster *api.Cluster, err error) {
62
-	watch, cancel := state.Watch(n.MemoryStore().WatchQueue(), state.EventCreateCluster{})
62
+	watch, cancel := state.Watch(n.MemoryStore().WatchQueue(), api.EventCreateCluster{})
63 63
 	defer cancel()
64 64
 
65 65
 	var clusters []*api.Cluster
... ...
@@ -76,7 +76,7 @@ func WaitForCluster(ctx context.Context, n *Node) (cluster *api.Cluster, err err
76 76
 	} else {
77 77
 		select {
78 78
 		case e := <-watch:
79
-			cluster = e.(state.EventCreateCluster).Cluster
79
+			cluster = e.(api.EventCreateCluster).Cluster
80 80
 		case <-ctx.Done():
81 81
 			return nil, ctx.Err()
82 82
 		}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"errors"
5 5
 
6 6
 	"github.com/docker/go-events"
7
+	"github.com/docker/swarmkit/api"
7 8
 	"github.com/docker/swarmkit/manager/state"
8 9
 )
9 10
 
... ...
@@ -12,32 +13,32 @@ import (
12 12
 func Apply(store *MemoryStore, item events.Event) (err error) {
13 13
 	return store.Update(func(tx Tx) error {
14 14
 		switch v := item.(type) {
15
-		case state.EventCreateTask:
15
+		case api.EventCreateTask:
16 16
 			return CreateTask(tx, v.Task)
17
-		case state.EventUpdateTask:
17
+		case api.EventUpdateTask:
18 18
 			return UpdateTask(tx, v.Task)
19
-		case state.EventDeleteTask:
19
+		case api.EventDeleteTask:
20 20
 			return DeleteTask(tx, v.Task.ID)
21 21
 
22
-		case state.EventCreateService:
22
+		case api.EventCreateService:
23 23
 			return CreateService(tx, v.Service)
24
-		case state.EventUpdateService:
24
+		case api.EventUpdateService:
25 25
 			return UpdateService(tx, v.Service)
26
-		case state.EventDeleteService:
26
+		case api.EventDeleteService:
27 27
 			return DeleteService(tx, v.Service.ID)
28 28
 
29
-		case state.EventCreateNetwork:
29
+		case api.EventCreateNetwork:
30 30
 			return CreateNetwork(tx, v.Network)
31
-		case state.EventUpdateNetwork:
31
+		case api.EventUpdateNetwork:
32 32
 			return UpdateNetwork(tx, v.Network)
33
-		case state.EventDeleteNetwork:
33
+		case api.EventDeleteNetwork:
34 34
 			return DeleteNetwork(tx, v.Network.ID)
35 35
 
36
-		case state.EventCreateNode:
36
+		case api.EventCreateNode:
37 37
 			return CreateNode(tx, v.Node)
38
-		case state.EventUpdateNode:
38
+		case api.EventUpdateNode:
39 39
 			return UpdateNode(tx, v.Node)
40
-		case state.EventDeleteNode:
40
+		case api.EventDeleteNode:
41 41
 			return DeleteNode(tx, v.Node.ID)
42 42
 
43 43
 		case state.EventCommit:
... ...
@@ -54,6 +54,16 @@ type byService string
54 54
 func (b byService) isBy() {
55 55
 }
56 56
 
57
+type byRuntime string
58
+
59
+func (b byRuntime) isBy() {
60
+}
61
+
62
+// ByRuntime creates an object to pass to Find to select by runtime.
63
+func ByRuntime(runtime string) By {
64
+	return byRuntime(runtime)
65
+}
66
+
57 67
 // ByServiceID creates an object to pass to Find to select by service.
58 68
 func ByServiceID(serviceID string) By {
59 69
 	return byService(serviceID)
... ...
@@ -143,3 +153,51 @@ func (b byReferencedSecretID) isBy() {
143 143
 func ByReferencedSecretID(secretID string) By {
144 144
 	return byReferencedSecretID(secretID)
145 145
 }
146
+
147
+type byKind string
148
+
149
+func (b byKind) isBy() {
150
+}
151
+
152
+// ByKind creates an object to pass to Find to search for a Resource of a
153
+// particular kind.
154
+func ByKind(kind string) By {
155
+	return byKind(kind)
156
+}
157
+
158
+type byCustom struct {
159
+	objType string
160
+	index   string
161
+	value   string
162
+}
163
+
164
+func (b byCustom) isBy() {
165
+}
166
+
167
+// ByCustom creates an object to pass to Find to search a custom index.
168
+func ByCustom(objType, index, value string) By {
169
+	return byCustom{
170
+		objType: objType,
171
+		index:   index,
172
+		value:   value,
173
+	}
174
+}
175
+
176
+type byCustomPrefix struct {
177
+	objType string
178
+	index   string
179
+	value   string
180
+}
181
+
182
+func (b byCustomPrefix) isBy() {
183
+}
184
+
185
+// ByCustomPrefix creates an object to pass to Find to search a custom index by
186
+// a value prefix.
187
+func ByCustomPrefix(objType, index, value string) By {
188
+	return byCustomPrefix{
189
+		objType: objType,
190
+		index:   index,
191
+		value:   value,
192
+	}
193
+}
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"strings"
5 5
 
6 6
 	"github.com/docker/swarmkit/api"
7
-	"github.com/docker/swarmkit/manager/state"
8 7
 	memdb "github.com/hashicorp/go-memdb"
9 8
 )
10 9
 
... ...
@@ -18,19 +17,23 @@ const (
18 18
 
19 19
 func init() {
20 20
 	register(ObjectStoreConfig{
21
-		Name: tableCluster,
22 21
 		Table: &memdb.TableSchema{
23 22
 			Name: tableCluster,
24 23
 			Indexes: map[string]*memdb.IndexSchema{
25 24
 				indexID: {
26 25
 					Name:    indexID,
27 26
 					Unique:  true,
28
-					Indexer: clusterIndexerByID{},
27
+					Indexer: api.ClusterIndexerByID{},
29 28
 				},
30 29
 				indexName: {
31 30
 					Name:    indexName,
32 31
 					Unique:  true,
33
-					Indexer: clusterIndexerByName{},
32
+					Indexer: api.ClusterIndexerByName{},
33
+				},
34
+				indexCustom: {
35
+					Name:         indexCustom,
36
+					Indexer:      api.ClusterCustomIndexer{},
37
+					AllowMissing: true,
34 38
 				},
35 39
 			},
36 40
 		},
... ...
@@ -56,7 +59,7 @@ func init() {
56 56
 			}
57 57
 			return nil
58 58
 		},
59
-		ApplyStoreAction: func(tx Tx, sa *api.StoreAction) error {
59
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
60 60
 			switch v := sa.Target.(type) {
61 61
 			case *api.StoreAction_Cluster:
62 62
 				obj := v.Cluster
... ...
@@ -71,64 +74,9 @@ func init() {
71 71
 			}
72 72
 			return errUnknownStoreAction
73 73
 		},
74
-		NewStoreAction: func(c state.Event) (api.StoreAction, error) {
75
-			var sa api.StoreAction
76
-			switch v := c.(type) {
77
-			case state.EventCreateCluster:
78
-				sa.Action = api.StoreActionKindCreate
79
-				sa.Target = &api.StoreAction_Cluster{
80
-					Cluster: v.Cluster,
81
-				}
82
-			case state.EventUpdateCluster:
83
-				sa.Action = api.StoreActionKindUpdate
84
-				sa.Target = &api.StoreAction_Cluster{
85
-					Cluster: v.Cluster,
86
-				}
87
-			case state.EventDeleteCluster:
88
-				sa.Action = api.StoreActionKindRemove
89
-				sa.Target = &api.StoreAction_Cluster{
90
-					Cluster: v.Cluster,
91
-				}
92
-			default:
93
-				return api.StoreAction{}, errUnknownStoreAction
94
-			}
95
-			return sa, nil
96
-		},
97 74
 	})
98 75
 }
99 76
 
100
-type clusterEntry struct {
101
-	*api.Cluster
102
-}
103
-
104
-func (c clusterEntry) ID() string {
105
-	return c.Cluster.ID
106
-}
107
-
108
-func (c clusterEntry) Meta() api.Meta {
109
-	return c.Cluster.Meta
110
-}
111
-
112
-func (c clusterEntry) SetMeta(meta api.Meta) {
113
-	c.Cluster.Meta = meta
114
-}
115
-
116
-func (c clusterEntry) Copy() Object {
117
-	return clusterEntry{c.Cluster.Copy()}
118
-}
119
-
120
-func (c clusterEntry) EventCreate() state.Event {
121
-	return state.EventCreateCluster{Cluster: c.Cluster}
122
-}
123
-
124
-func (c clusterEntry) EventUpdate() state.Event {
125
-	return state.EventUpdateCluster{Cluster: c.Cluster}
126
-}
127
-
128
-func (c clusterEntry) EventDelete() state.Event {
129
-	return state.EventDeleteCluster{Cluster: c.Cluster}
130
-}
131
-
132 77
 // CreateCluster adds a new cluster to the store.
133 78
 // Returns ErrExist if the ID is already taken.
134 79
 func CreateCluster(tx Tx, c *api.Cluster) error {
... ...
@@ -137,7 +85,7 @@ func CreateCluster(tx Tx, c *api.Cluster) error {
137 137
 		return ErrNameConflict
138 138
 	}
139 139
 
140
-	return tx.create(tableCluster, clusterEntry{c})
140
+	return tx.create(tableCluster, c)
141 141
 }
142 142
 
143 143
 // UpdateCluster updates an existing cluster in the store.
... ...
@@ -145,12 +93,12 @@ func CreateCluster(tx Tx, c *api.Cluster) error {
145 145
 func UpdateCluster(tx Tx, c *api.Cluster) error {
146 146
 	// Ensure the name is either not in use or already used by this same Cluster.
147 147
 	if existing := tx.lookup(tableCluster, indexName, strings.ToLower(c.Spec.Annotations.Name)); existing != nil {
148
-		if existing.ID() != c.ID {
148
+		if existing.GetID() != c.ID {
149 149
 			return ErrNameConflict
150 150
 		}
151 151
 	}
152 152
 
153
-	return tx.update(tableCluster, clusterEntry{c})
153
+	return tx.update(tableCluster, c)
154 154
 }
155 155
 
156 156
 // DeleteCluster removes a cluster from the store.
... ...
@@ -166,14 +114,14 @@ func GetCluster(tx ReadTx, id string) *api.Cluster {
166 166
 	if n == nil {
167 167
 		return nil
168 168
 	}
169
-	return n.(clusterEntry).Cluster
169
+	return n.(*api.Cluster)
170 170
 }
171 171
 
172 172
 // FindClusters selects a set of clusters and returns them.
173 173
 func FindClusters(tx ReadTx, by By) ([]*api.Cluster, error) {
174 174
 	checkType := func(by By) error {
175 175
 		switch by.(type) {
176
-		case byName, byNamePrefix, byIDPrefix:
176
+		case byName, byNamePrefix, byIDPrefix, byCustom, byCustomPrefix:
177 177
 			return nil
178 178
 		default:
179 179
 			return ErrInvalidFindBy
... ...
@@ -181,51 +129,10 @@ func FindClusters(tx ReadTx, by By) ([]*api.Cluster, error) {
181 181
 	}
182 182
 
183 183
 	clusterList := []*api.Cluster{}
184
-	appendResult := func(o Object) {
185
-		clusterList = append(clusterList, o.(clusterEntry).Cluster)
184
+	appendResult := func(o api.StoreObject) {
185
+		clusterList = append(clusterList, o.(*api.Cluster))
186 186
 	}
187 187
 
188 188
 	err := tx.find(tableCluster, by, checkType, appendResult)
189 189
 	return clusterList, err
190 190
 }
191
-
192
-type clusterIndexerByID struct{}
193
-
194
-func (ci clusterIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
195
-	return fromArgs(args...)
196
-}
197
-
198
-func (ci clusterIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
199
-	c, ok := obj.(clusterEntry)
200
-	if !ok {
201
-		panic("unexpected type passed to FromObject")
202
-	}
203
-
204
-	// Add the null character as a terminator
205
-	val := c.Cluster.ID + "\x00"
206
-	return true, []byte(val), nil
207
-}
208
-
209
-func (ci clusterIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
210
-	return prefixFromArgs(args...)
211
-}
212
-
213
-type clusterIndexerByName struct{}
214
-
215
-func (ci clusterIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
216
-	return fromArgs(args...)
217
-}
218
-
219
-func (ci clusterIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
220
-	c, ok := obj.(clusterEntry)
221
-	if !ok {
222
-		panic("unexpected type passed to FromObject")
223
-	}
224
-
225
-	// Add the null character as a terminator
226
-	return true, []byte(strings.ToLower(c.Spec.Annotations.Name) + "\x00"), nil
227
-}
228
-
229
-func (ci clusterIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
230
-	return prefixFromArgs(args...)
231
-}
232 191
new file mode 100644
... ...
@@ -0,0 +1,150 @@
0
+package store
1
+
2
+import (
3
+	"errors"
4
+	"strings"
5
+
6
+	"github.com/docker/swarmkit/api"
7
+	memdb "github.com/hashicorp/go-memdb"
8
+)
9
+
10
+const tableExtension = "extension"
11
+
12
+func init() {
13
+	register(ObjectStoreConfig{
14
+		Table: &memdb.TableSchema{
15
+			Name: tableExtension,
16
+			Indexes: map[string]*memdb.IndexSchema{
17
+				indexID: {
18
+					Name:    indexID,
19
+					Unique:  true,
20
+					Indexer: api.ExtensionIndexerByID{},
21
+				},
22
+				indexName: {
23
+					Name:    indexName,
24
+					Unique:  true,
25
+					Indexer: api.ExtensionIndexerByName{},
26
+				},
27
+				indexCustom: {
28
+					Name:         indexCustom,
29
+					Indexer:      api.ExtensionCustomIndexer{},
30
+					AllowMissing: true,
31
+				},
32
+			},
33
+		},
34
+		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
35
+			var err error
36
+			snapshot.Extensions, err = FindExtensions(tx, All)
37
+			return err
38
+		},
39
+		Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
40
+			extensions, err := FindExtensions(tx, All)
41
+			if err != nil {
42
+				return err
43
+			}
44
+			for _, e := range extensions {
45
+				if err := DeleteExtension(tx, e.ID); err != nil {
46
+					return err
47
+				}
48
+			}
49
+			for _, e := range snapshot.Extensions {
50
+				if err := CreateExtension(tx, e); err != nil {
51
+					return err
52
+				}
53
+			}
54
+			return nil
55
+		},
56
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
57
+			switch v := sa.Target.(type) {
58
+			case *api.StoreAction_Extension:
59
+				obj := v.Extension
60
+				switch sa.Action {
61
+				case api.StoreActionKindCreate:
62
+					return CreateExtension(tx, obj)
63
+				case api.StoreActionKindUpdate:
64
+					return UpdateExtension(tx, obj)
65
+				case api.StoreActionKindRemove:
66
+					return DeleteExtension(tx, obj.ID)
67
+				}
68
+			}
69
+			return errUnknownStoreAction
70
+		},
71
+	})
72
+}
73
+
74
+type extensionEntry struct {
75
+	*api.Extension
76
+}
77
+
78
+// CreateExtension adds a new extension to the store.
79
+// Returns ErrExist if the ID is already taken.
80
+func CreateExtension(tx Tx, e *api.Extension) error {
81
+	// Ensure the name is not already in use.
82
+	if tx.lookup(tableExtension, indexName, strings.ToLower(e.Annotations.Name)) != nil {
83
+		return ErrNameConflict
84
+	}
85
+
86
+	// It can't conflict with built-in kinds either.
87
+	if _, ok := schema.Tables[e.Annotations.Name]; ok {
88
+		return ErrNameConflict
89
+	}
90
+
91
+	return tx.create(tableExtension, extensionEntry{e})
92
+}
93
+
94
+// UpdateExtension updates an existing extension in the store.
95
+// Returns ErrNotExist if the object doesn't exist.
96
+func UpdateExtension(tx Tx, e *api.Extension) error {
97
+	// TODO(aaronl): For the moment, extensions are immutable
98
+	return errors.New("extensions are immutable")
99
+}
100
+
101
+// DeleteExtension removes an extension from the store.
102
+// Returns ErrNotExist if the object doesn't exist.
103
+func DeleteExtension(tx Tx, id string) error {
104
+	e := tx.get(tableExtension, id)
105
+	if e == nil {
106
+		return ErrNotExist
107
+	}
108
+
109
+	resources, err := FindResources(tx, ByKind(e.(extensionEntry).Annotations.Name))
110
+	if err != nil {
111
+		return err
112
+	}
113
+
114
+	if len(resources) != 0 {
115
+		return errors.New("cannot delete extension because objects of this type exist in the data store")
116
+	}
117
+
118
+	return tx.delete(tableExtension, id)
119
+}
120
+
121
+// GetExtension looks up an extension by ID.
122
+// Returns nil if the object doesn't exist.
123
+func GetExtension(tx ReadTx, id string) *api.Extension {
124
+	e := tx.get(tableExtension, id)
125
+	if e == nil {
126
+		return nil
127
+	}
128
+	return e.(extensionEntry).Extension
129
+}
130
+
131
+// FindExtensions selects a set of extensions and returns them.
132
+func FindExtensions(tx ReadTx, by By) ([]*api.Extension, error) {
133
+	checkType := func(by By) error {
134
+		switch by.(type) {
135
+		case byIDPrefix, byName, byCustom, byCustomPrefix:
136
+			return nil
137
+		default:
138
+			return ErrInvalidFindBy
139
+		}
140
+	}
141
+
142
+	extensionList := []*api.Extension{}
143
+	appendResult := func(o api.StoreObject) {
144
+		extensionList = append(extensionList, o.(extensionEntry).Extension)
145
+	}
146
+
147
+	err := tx.find(tableExtension, by, checkType, appendResult)
148
+	return extensionList, err
149
+}
... ...
@@ -22,6 +22,7 @@ import (
22 22
 const (
23 23
 	indexID           = "id"
24 24
 	indexName         = "name"
25
+	indexRuntime      = "runtime"
25 26
 	indexServiceID    = "serviceid"
26 27
 	indexNodeID       = "nodeid"
27 28
 	indexSlot         = "slot"
... ...
@@ -31,6 +32,8 @@ const (
31 31
 	indexMembership   = "membership"
32 32
 	indexNetwork      = "network"
33 33
 	indexSecret       = "secret"
34
+	indexKind         = "kind"
35
+	indexCustom       = "custom"
34 36
 
35 37
 	prefix = "_prefix"
36 38
 
... ...
@@ -71,7 +74,7 @@ var (
71 71
 
72 72
 func register(os ObjectStoreConfig) {
73 73
 	objectStorers = append(objectStorers, os)
74
-	schema.Tables[os.Name] = os.Table
74
+	schema.Tables[os.Table.Name] = os.Table
75 75
 }
76 76
 
77 77
 // MemoryStore is a concurrency-safe, in-memory implementation of the Store
... ...
@@ -140,9 +143,9 @@ func prefixFromArgs(args ...interface{}) ([]byte, error) {
140 140
 // consistent view of the data that cannot be affected by other
141 141
 // transactions.
142 142
 type ReadTx interface {
143
-	lookup(table, index, id string) Object
144
-	get(table, id string) Object
145
-	find(table string, by By, checkType func(By) error, appendResult func(Object)) error
143
+	lookup(table, index, id string) api.StoreObject
144
+	get(table, id string) api.StoreObject
145
+	find(table string, by By, checkType func(By) error, appendResult func(api.StoreObject)) error
146 146
 }
147 147
 
148 148
 type readTx struct {
... ...
@@ -166,19 +169,19 @@ func (s *MemoryStore) View(cb func(ReadTx)) {
166 166
 // until the transaction is over.
167 167
 type Tx interface {
168 168
 	ReadTx
169
-	create(table string, o Object) error
170
-	update(table string, o Object) error
169
+	create(table string, o api.StoreObject) error
170
+	update(table string, o api.StoreObject) error
171 171
 	delete(table, id string) error
172 172
 }
173 173
 
174 174
 type tx struct {
175 175
 	readTx
176 176
 	curVersion *api.Version
177
-	changelist []state.Event
177
+	changelist []api.Event
178 178
 }
179 179
 
180 180
 // ApplyStoreActions updates a store based on StoreAction messages.
181
-func (s *MemoryStore) ApplyStoreActions(actions []*api.StoreAction) error {
181
+func (s *MemoryStore) ApplyStoreActions(actions []api.StoreAction) error {
182 182
 	s.updateLock.Lock()
183 183
 	memDBTx := s.memDB.Txn(true)
184 184
 
... ...
@@ -208,7 +211,7 @@ func (s *MemoryStore) ApplyStoreActions(actions []*api.StoreAction) error {
208 208
 	return nil
209 209
 }
210 210
 
211
-func applyStoreAction(tx Tx, sa *api.StoreAction) error {
211
+func applyStoreAction(tx Tx, sa api.StoreAction) error {
212 212
 	for _, os := range objectStorers {
213 213
 		err := os.ApplyStoreAction(tx, sa)
214 214
 		if err != errUnknownStoreAction {
... ...
@@ -238,7 +241,7 @@ func (s *MemoryStore) update(proposer state.Proposer, cb func(Tx) error) error {
238 238
 		if proposer == nil {
239 239
 			memDBTx.Commit()
240 240
 		} else {
241
-			var sa []*api.StoreAction
241
+			var sa []api.StoreAction
242 242
 			sa, err = tx.changelistStoreActions()
243 243
 
244 244
 			if err == nil {
... ...
@@ -310,7 +313,7 @@ func (batch *Batch) Update(cb func(Tx) error) error {
310 310
 	batch.applied++
311 311
 
312 312
 	for batch.changelistLen < len(batch.tx.changelist) {
313
-		sa, err := newStoreAction(batch.tx.changelist[batch.changelistLen])
313
+		sa, err := api.NewStoreAction(batch.tx.changelist[batch.changelistLen])
314 314
 		if err != nil {
315 315
 			return err
316 316
 		}
... ...
@@ -348,7 +351,7 @@ func (batch *Batch) newTx() {
348 348
 
349 349
 func (batch *Batch) commit() error {
350 350
 	if batch.store.proposer != nil {
351
-		var sa []*api.StoreAction
351
+		var sa []api.StoreAction
352 352
 		sa, batch.err = batch.tx.changelistStoreActions()
353 353
 
354 354
 		if batch.err == nil {
... ...
@@ -423,24 +426,11 @@ func (tx *tx) init(memDBTx *memdb.Txn, curVersion *api.Version) {
423 423
 	tx.changelist = nil
424 424
 }
425 425
 
426
-func newStoreAction(c state.Event) (*api.StoreAction, error) {
427
-	for _, os := range objectStorers {
428
-		sa, err := os.NewStoreAction(c)
429
-		if err == nil {
430
-			return &sa, nil
431
-		} else if err != errUnknownStoreAction {
432
-			return nil, err
433
-		}
434
-	}
435
-
436
-	return nil, errors.New("unrecognized event type")
437
-}
438
-
439
-func (tx tx) changelistStoreActions() ([]*api.StoreAction, error) {
440
-	var actions []*api.StoreAction
426
+func (tx tx) changelistStoreActions() ([]api.StoreAction, error) {
427
+	var actions []api.StoreAction
441 428
 
442 429
 	for _, c := range tx.changelist {
443
-		sa, err := newStoreAction(c)
430
+		sa, err := api.NewStoreAction(c)
444 431
 		if err != nil {
445 432
 			return nil, err
446 433
 		}
... ...
@@ -451,26 +441,26 @@ func (tx tx) changelistStoreActions() ([]*api.StoreAction, error) {
451 451
 }
452 452
 
453 453
 // lookup is an internal typed wrapper around memdb.
454
-func (tx readTx) lookup(table, index, id string) Object {
454
+func (tx readTx) lookup(table, index, id string) api.StoreObject {
455 455
 	j, err := tx.memDBTx.First(table, index, id)
456 456
 	if err != nil {
457 457
 		return nil
458 458
 	}
459 459
 	if j != nil {
460
-		return j.(Object)
460
+		return j.(api.StoreObject)
461 461
 	}
462 462
 	return nil
463 463
 }
464 464
 
465 465
 // create adds a new object to the store.
466 466
 // Returns ErrExist if the ID is already taken.
467
-func (tx *tx) create(table string, o Object) error {
468
-	if tx.lookup(table, indexID, o.ID()) != nil {
467
+func (tx *tx) create(table string, o api.StoreObject) error {
468
+	if tx.lookup(table, indexID, o.GetID()) != nil {
469 469
 		return ErrExist
470 470
 	}
471 471
 
472
-	copy := o.Copy()
473
-	meta := copy.Meta()
472
+	copy := o.CopyStoreObject()
473
+	meta := copy.GetMeta()
474 474
 	if err := touchMeta(&meta, tx.curVersion); err != nil {
475 475
 		return err
476 476
 	}
... ...
@@ -486,20 +476,21 @@ func (tx *tx) create(table string, o Object) error {
486 486
 
487 487
 // Update updates an existing object in the store.
488 488
 // Returns ErrNotExist if the object doesn't exist.
489
-func (tx *tx) update(table string, o Object) error {
490
-	oldN := tx.lookup(table, indexID, o.ID())
489
+func (tx *tx) update(table string, o api.StoreObject) error {
490
+	oldN := tx.lookup(table, indexID, o.GetID())
491 491
 	if oldN == nil {
492 492
 		return ErrNotExist
493 493
 	}
494 494
 
495
+	meta := o.GetMeta()
496
+
495 497
 	if tx.curVersion != nil {
496
-		if oldN.(Object).Meta().Version != o.Meta().Version {
498
+		if oldN.GetMeta().Version != meta.Version {
497 499
 			return ErrSequenceConflict
498 500
 		}
499 501
 	}
500 502
 
501
-	copy := o.Copy()
502
-	meta := copy.Meta()
503
+	copy := o.CopyStoreObject()
503 504
 	if err := touchMeta(&meta, tx.curVersion); err != nil {
504 505
 		return err
505 506
 	}
... ...
@@ -530,12 +521,12 @@ func (tx *tx) delete(table, id string) error {
530 530
 
531 531
 // Get looks up an object by ID.
532 532
 // Returns nil if the object doesn't exist.
533
-func (tx readTx) get(table, id string) Object {
533
+func (tx readTx) get(table, id string) api.StoreObject {
534 534
 	o := tx.lookup(table, indexID, id)
535 535
 	if o == nil {
536 536
 		return nil
537 537
 	}
538
-	return o.Copy()
538
+	return o.CopyStoreObject()
539 539
 }
540 540
 
541 541
 // findIterators returns a slice of iterators. The union of items from these
... ...
@@ -584,6 +575,12 @@ func (tx readTx) findIterators(table string, by By, checkType func(By) error) ([
584 584
 			return nil, err
585 585
 		}
586 586
 		return []memdb.ResultIterator{it}, nil
587
+	case byRuntime:
588
+		it, err := tx.memDBTx.Get(table, indexRuntime, string(v))
589
+		if err != nil {
590
+			return nil, err
591
+		}
592
+		return []memdb.ResultIterator{it}, nil
587 593
 	case byNode:
588 594
 		it, err := tx.memDBTx.Get(table, indexNodeID, string(v))
589 595
 		if err != nil {
... ...
@@ -638,13 +635,43 @@ func (tx readTx) findIterators(table string, by By, checkType func(By) error) ([
638 638
 			return nil, err
639 639
 		}
640 640
 		return []memdb.ResultIterator{it}, nil
641
+	case byKind:
642
+		it, err := tx.memDBTx.Get(table, indexKind, string(v))
643
+		if err != nil {
644
+			return nil, err
645
+		}
646
+		return []memdb.ResultIterator{it}, nil
647
+	case byCustom:
648
+		var key string
649
+		if v.objType != "" {
650
+			key = v.objType + "|" + v.index + "|" + v.value
651
+		} else {
652
+			key = v.index + "|" + v.value
653
+		}
654
+		it, err := tx.memDBTx.Get(table, indexCustom, key)
655
+		if err != nil {
656
+			return nil, err
657
+		}
658
+		return []memdb.ResultIterator{it}, nil
659
+	case byCustomPrefix:
660
+		var key string
661
+		if v.objType != "" {
662
+			key = v.objType + "|" + v.index + "|" + v.value
663
+		} else {
664
+			key = v.index + "|" + v.value
665
+		}
666
+		it, err := tx.memDBTx.Get(table, indexCustom+prefix, key)
667
+		if err != nil {
668
+			return nil, err
669
+		}
670
+		return []memdb.ResultIterator{it}, nil
641 671
 	default:
642 672
 		return nil, ErrInvalidFindBy
643 673
 	}
644 674
 }
645 675
 
646 676
 // find selects a set of objects calls a callback for each matching object.
647
-func (tx readTx) find(table string, by By, checkType func(By) error, appendResult func(Object)) error {
677
+func (tx readTx) find(table string, by By, checkType func(By) error, appendResult func(api.StoreObject)) error {
648 678
 	fromResultIterators := func(its ...memdb.ResultIterator) {
649 679
 		ids := make(map[string]struct{})
650 680
 		for _, it := range its {
... ...
@@ -653,10 +680,10 @@ func (tx readTx) find(table string, by By, checkType func(By) error, appendResul
653 653
 				if obj == nil {
654 654
 					break
655 655
 				}
656
-				o := obj.(Object)
657
-				id := o.ID()
656
+				o := obj.(api.StoreObject)
657
+				id := o.GetID()
658 658
 				if _, exists := ids[id]; !exists {
659
-					appendResult(o.Copy())
659
+					appendResult(o.CopyStoreObject())
660 660
 					ids[id] = struct{}{}
661 661
 				}
662 662
 			}
... ...
@@ -709,7 +736,7 @@ func (s *MemoryStore) WatchQueue() *watch.Queue {
709 709
 // released with watch.StopWatch when it is no longer needed. The channel is
710 710
 // guaranteed to get all events after the moment of the snapshot, and only
711 711
 // those events.
712
-func ViewAndWatch(store *MemoryStore, cb func(ReadTx) error, specifiers ...state.Event) (watch chan events.Event, cancel func(), err error) {
712
+func ViewAndWatch(store *MemoryStore, cb func(ReadTx) error, specifiers ...api.Event) (watch chan events.Event, cancel func(), err error) {
713 713
 	// Using Update to lock the store and guarantee consistency between
714 714
 	// the watcher and the the state seen by the callback. snapshotReadTx
715 715
 	// exposes this Tx as a ReadTx so the callback can't modify it.
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"strings"
5 5
 
6 6
 	"github.com/docker/swarmkit/api"
7
-	"github.com/docker/swarmkit/manager/state"
8 7
 	memdb "github.com/hashicorp/go-memdb"
9 8
 )
10 9
 
... ...
@@ -12,19 +11,23 @@ const tableNetwork = "network"
12 12
 
13 13
 func init() {
14 14
 	register(ObjectStoreConfig{
15
-		Name: tableNetwork,
16 15
 		Table: &memdb.TableSchema{
17 16
 			Name: tableNetwork,
18 17
 			Indexes: map[string]*memdb.IndexSchema{
19 18
 				indexID: {
20 19
 					Name:    indexID,
21 20
 					Unique:  true,
22
-					Indexer: networkIndexerByID{},
21
+					Indexer: api.NetworkIndexerByID{},
23 22
 				},
24 23
 				indexName: {
25 24
 					Name:    indexName,
26 25
 					Unique:  true,
27
-					Indexer: networkIndexerByName{},
26
+					Indexer: api.NetworkIndexerByName{},
27
+				},
28
+				indexCustom: {
29
+					Name:         indexCustom,
30
+					Indexer:      api.NetworkCustomIndexer{},
31
+					AllowMissing: true,
28 32
 				},
29 33
 			},
30 34
 		},
... ...
@@ -50,7 +53,7 @@ func init() {
50 50
 			}
51 51
 			return nil
52 52
 		},
53
-		ApplyStoreAction: func(tx Tx, sa *api.StoreAction) error {
53
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
54 54
 			switch v := sa.Target.(type) {
55 55
 			case *api.StoreAction_Network:
56 56
 				obj := v.Network
... ...
@@ -65,64 +68,9 @@ func init() {
65 65
 			}
66 66
 			return errUnknownStoreAction
67 67
 		},
68
-		NewStoreAction: func(c state.Event) (api.StoreAction, error) {
69
-			var sa api.StoreAction
70
-			switch v := c.(type) {
71
-			case state.EventCreateNetwork:
72
-				sa.Action = api.StoreActionKindCreate
73
-				sa.Target = &api.StoreAction_Network{
74
-					Network: v.Network,
75
-				}
76
-			case state.EventUpdateNetwork:
77
-				sa.Action = api.StoreActionKindUpdate
78
-				sa.Target = &api.StoreAction_Network{
79
-					Network: v.Network,
80
-				}
81
-			case state.EventDeleteNetwork:
82
-				sa.Action = api.StoreActionKindRemove
83
-				sa.Target = &api.StoreAction_Network{
84
-					Network: v.Network,
85
-				}
86
-			default:
87
-				return api.StoreAction{}, errUnknownStoreAction
88
-			}
89
-			return sa, nil
90
-		},
91 68
 	})
92 69
 }
93 70
 
94
-type networkEntry struct {
95
-	*api.Network
96
-}
97
-
98
-func (n networkEntry) ID() string {
99
-	return n.Network.ID
100
-}
101
-
102
-func (n networkEntry) Meta() api.Meta {
103
-	return n.Network.Meta
104
-}
105
-
106
-func (n networkEntry) SetMeta(meta api.Meta) {
107
-	n.Network.Meta = meta
108
-}
109
-
110
-func (n networkEntry) Copy() Object {
111
-	return networkEntry{n.Network.Copy()}
112
-}
113
-
114
-func (n networkEntry) EventCreate() state.Event {
115
-	return state.EventCreateNetwork{Network: n.Network}
116
-}
117
-
118
-func (n networkEntry) EventUpdate() state.Event {
119
-	return state.EventUpdateNetwork{Network: n.Network}
120
-}
121
-
122
-func (n networkEntry) EventDelete() state.Event {
123
-	return state.EventDeleteNetwork{Network: n.Network}
124
-}
125
-
126 71
 // CreateNetwork adds a new network to the store.
127 72
 // Returns ErrExist if the ID is already taken.
128 73
 func CreateNetwork(tx Tx, n *api.Network) error {
... ...
@@ -131,7 +79,7 @@ func CreateNetwork(tx Tx, n *api.Network) error {
131 131
 		return ErrNameConflict
132 132
 	}
133 133
 
134
-	return tx.create(tableNetwork, networkEntry{n})
134
+	return tx.create(tableNetwork, n)
135 135
 }
136 136
 
137 137
 // UpdateNetwork updates an existing network in the store.
... ...
@@ -139,12 +87,12 @@ func CreateNetwork(tx Tx, n *api.Network) error {
139 139
 func UpdateNetwork(tx Tx, n *api.Network) error {
140 140
 	// Ensure the name is either not in use or already used by this same Network.
141 141
 	if existing := tx.lookup(tableNetwork, indexName, strings.ToLower(n.Spec.Annotations.Name)); existing != nil {
142
-		if existing.ID() != n.ID {
142
+		if existing.GetID() != n.ID {
143 143
 			return ErrNameConflict
144 144
 		}
145 145
 	}
146 146
 
147
-	return tx.update(tableNetwork, networkEntry{n})
147
+	return tx.update(tableNetwork, n)
148 148
 }
149 149
 
150 150
 // DeleteNetwork removes a network from the store.
... ...
@@ -160,14 +108,14 @@ func GetNetwork(tx ReadTx, id string) *api.Network {
160 160
 	if n == nil {
161 161
 		return nil
162 162
 	}
163
-	return n.(networkEntry).Network
163
+	return n.(*api.Network)
164 164
 }
165 165
 
166 166
 // FindNetworks selects a set of networks and returns them.
167 167
 func FindNetworks(tx ReadTx, by By) ([]*api.Network, error) {
168 168
 	checkType := func(by By) error {
169 169
 		switch by.(type) {
170
-		case byName, byNamePrefix, byIDPrefix:
170
+		case byName, byNamePrefix, byIDPrefix, byCustom, byCustomPrefix:
171 171
 			return nil
172 172
 		default:
173 173
 			return ErrInvalidFindBy
... ...
@@ -175,51 +123,10 @@ func FindNetworks(tx ReadTx, by By) ([]*api.Network, error) {
175 175
 	}
176 176
 
177 177
 	networkList := []*api.Network{}
178
-	appendResult := func(o Object) {
179
-		networkList = append(networkList, o.(networkEntry).Network)
178
+	appendResult := func(o api.StoreObject) {
179
+		networkList = append(networkList, o.(*api.Network))
180 180
 	}
181 181
 
182 182
 	err := tx.find(tableNetwork, by, checkType, appendResult)
183 183
 	return networkList, err
184 184
 }
185
-
186
-type networkIndexerByID struct{}
187
-
188
-func (ni networkIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
189
-	return fromArgs(args...)
190
-}
191
-
192
-func (ni networkIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
193
-	n, ok := obj.(networkEntry)
194
-	if !ok {
195
-		panic("unexpected type passed to FromObject")
196
-	}
197
-
198
-	// Add the null character as a terminator
199
-	val := n.Network.ID + "\x00"
200
-	return true, []byte(val), nil
201
-}
202
-
203
-func (ni networkIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
204
-	return prefixFromArgs(args...)
205
-}
206
-
207
-type networkIndexerByName struct{}
208
-
209
-func (ni networkIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
210
-	return fromArgs(args...)
211
-}
212
-
213
-func (ni networkIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
214
-	n, ok := obj.(networkEntry)
215
-	if !ok {
216
-		panic("unexpected type passed to FromObject")
217
-	}
218
-
219
-	// Add the null character as a terminator
220
-	return true, []byte(strings.ToLower(n.Spec.Annotations.Name) + "\x00"), nil
221
-}
222
-
223
-func (ni networkIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
224
-	return prefixFromArgs(args...)
225
-}
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"strings"
6 6
 
7 7
 	"github.com/docker/swarmkit/api"
8
-	"github.com/docker/swarmkit/manager/state"
9 8
 	memdb "github.com/hashicorp/go-memdb"
10 9
 )
11 10
 
... ...
@@ -13,14 +12,13 @@ const tableNode = "node"
13 13
 
14 14
 func init() {
15 15
 	register(ObjectStoreConfig{
16
-		Name: tableNode,
17 16
 		Table: &memdb.TableSchema{
18 17
 			Name: tableNode,
19 18
 			Indexes: map[string]*memdb.IndexSchema{
20 19
 				indexID: {
21 20
 					Name:    indexID,
22 21
 					Unique:  true,
23
-					Indexer: nodeIndexerByID{},
22
+					Indexer: api.NodeIndexerByID{},
24 23
 				},
25 24
 				// TODO(aluzzardi): Use `indexHostname` instead.
26 25
 				indexName: {
... ...
@@ -36,6 +34,11 @@ func init() {
36 36
 					Name:    indexMembership,
37 37
 					Indexer: nodeIndexerByMembership{},
38 38
 				},
39
+				indexCustom: {
40
+					Name:         indexCustom,
41
+					Indexer:      api.NodeCustomIndexer{},
42
+					AllowMissing: true,
43
+				},
39 44
 			},
40 45
 		},
41 46
 		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
... ...
@@ -60,7 +63,7 @@ func init() {
60 60
 			}
61 61
 			return nil
62 62
 		},
63
-		ApplyStoreAction: func(tx Tx, sa *api.StoreAction) error {
63
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
64 64
 			switch v := sa.Target.(type) {
65 65
 			case *api.StoreAction_Node:
66 66
 				obj := v.Node
... ...
@@ -75,74 +78,19 @@ func init() {
75 75
 			}
76 76
 			return errUnknownStoreAction
77 77
 		},
78
-		NewStoreAction: func(c state.Event) (api.StoreAction, error) {
79
-			var sa api.StoreAction
80
-			switch v := c.(type) {
81
-			case state.EventCreateNode:
82
-				sa.Action = api.StoreActionKindCreate
83
-				sa.Target = &api.StoreAction_Node{
84
-					Node: v.Node,
85
-				}
86
-			case state.EventUpdateNode:
87
-				sa.Action = api.StoreActionKindUpdate
88
-				sa.Target = &api.StoreAction_Node{
89
-					Node: v.Node,
90
-				}
91
-			case state.EventDeleteNode:
92
-				sa.Action = api.StoreActionKindRemove
93
-				sa.Target = &api.StoreAction_Node{
94
-					Node: v.Node,
95
-				}
96
-			default:
97
-				return api.StoreAction{}, errUnknownStoreAction
98
-			}
99
-			return sa, nil
100
-		},
101 78
 	})
102 79
 }
103 80
 
104
-type nodeEntry struct {
105
-	*api.Node
106
-}
107
-
108
-func (n nodeEntry) ID() string {
109
-	return n.Node.ID
110
-}
111
-
112
-func (n nodeEntry) Meta() api.Meta {
113
-	return n.Node.Meta
114
-}
115
-
116
-func (n nodeEntry) SetMeta(meta api.Meta) {
117
-	n.Node.Meta = meta
118
-}
119
-
120
-func (n nodeEntry) Copy() Object {
121
-	return nodeEntry{n.Node.Copy()}
122
-}
123
-
124
-func (n nodeEntry) EventCreate() state.Event {
125
-	return state.EventCreateNode{Node: n.Node}
126
-}
127
-
128
-func (n nodeEntry) EventUpdate() state.Event {
129
-	return state.EventUpdateNode{Node: n.Node}
130
-}
131
-
132
-func (n nodeEntry) EventDelete() state.Event {
133
-	return state.EventDeleteNode{Node: n.Node}
134
-}
135
-
136 81
 // CreateNode adds a new node to the store.
137 82
 // Returns ErrExist if the ID is already taken.
138 83
 func CreateNode(tx Tx, n *api.Node) error {
139
-	return tx.create(tableNode, nodeEntry{n})
84
+	return tx.create(tableNode, n)
140 85
 }
141 86
 
142 87
 // UpdateNode updates an existing node in the store.
143 88
 // Returns ErrNotExist if the node doesn't exist.
144 89
 func UpdateNode(tx Tx, n *api.Node) error {
145
-	return tx.update(tableNode, nodeEntry{n})
90
+	return tx.update(tableNode, n)
146 91
 }
147 92
 
148 93
 // DeleteNode removes a node from the store.
... ...
@@ -158,14 +106,14 @@ func GetNode(tx ReadTx, id string) *api.Node {
158 158
 	if n == nil {
159 159
 		return nil
160 160
 	}
161
-	return n.(nodeEntry).Node
161
+	return n.(*api.Node)
162 162
 }
163 163
 
164 164
 // FindNodes selects a set of nodes and returns them.
165 165
 func FindNodes(tx ReadTx, by By) ([]*api.Node, error) {
166 166
 	checkType := func(by By) error {
167 167
 		switch by.(type) {
168
-		case byName, byNamePrefix, byIDPrefix, byRole, byMembership:
168
+		case byName, byNamePrefix, byIDPrefix, byRole, byMembership, byCustom, byCustomPrefix:
169 169
 			return nil
170 170
 		default:
171 171
 			return ErrInvalidFindBy
... ...
@@ -173,35 +121,14 @@ func FindNodes(tx ReadTx, by By) ([]*api.Node, error) {
173 173
 	}
174 174
 
175 175
 	nodeList := []*api.Node{}
176
-	appendResult := func(o Object) {
177
-		nodeList = append(nodeList, o.(nodeEntry).Node)
176
+	appendResult := func(o api.StoreObject) {
177
+		nodeList = append(nodeList, o.(*api.Node))
178 178
 	}
179 179
 
180 180
 	err := tx.find(tableNode, by, checkType, appendResult)
181 181
 	return nodeList, err
182 182
 }
183 183
 
184
-type nodeIndexerByID struct{}
185
-
186
-func (ni nodeIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
187
-	return fromArgs(args...)
188
-}
189
-
190
-func (ni nodeIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
191
-	n, ok := obj.(nodeEntry)
192
-	if !ok {
193
-		panic("unexpected type passed to FromObject")
194
-	}
195
-
196
-	// Add the null character as a terminator
197
-	val := n.Node.ID + "\x00"
198
-	return true, []byte(val), nil
199
-}
200
-
201
-func (ni nodeIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
202
-	return prefixFromArgs(args...)
203
-}
204
-
205 184
 type nodeIndexerByHostname struct{}
206 185
 
207 186
 func (ni nodeIndexerByHostname) FromArgs(args ...interface{}) ([]byte, error) {
... ...
@@ -209,10 +136,7 @@ func (ni nodeIndexerByHostname) FromArgs(args ...interface{}) ([]byte, error) {
209 209
 }
210 210
 
211 211
 func (ni nodeIndexerByHostname) FromObject(obj interface{}) (bool, []byte, error) {
212
-	n, ok := obj.(nodeEntry)
213
-	if !ok {
214
-		panic("unexpected type passed to FromObject")
215
-	}
212
+	n := obj.(*api.Node)
216 213
 
217 214
 	if n.Description == nil {
218 215
 		return false, nil, nil
... ...
@@ -232,10 +156,7 @@ func (ni nodeIndexerByRole) FromArgs(args ...interface{}) ([]byte, error) {
232 232
 }
233 233
 
234 234
 func (ni nodeIndexerByRole) FromObject(obj interface{}) (bool, []byte, error) {
235
-	n, ok := obj.(nodeEntry)
236
-	if !ok {
237
-		panic("unexpected type passed to FromObject")
238
-	}
235
+	n := obj.(*api.Node)
239 236
 
240 237
 	// Add the null character as a terminator
241 238
 	return true, []byte(strconv.FormatInt(int64(n.Role), 10) + "\x00"), nil
... ...
@@ -248,10 +169,7 @@ func (ni nodeIndexerByMembership) FromArgs(args ...interface{}) ([]byte, error)
248 248
 }
249 249
 
250 250
 func (ni nodeIndexerByMembership) FromObject(obj interface{}) (bool, []byte, error) {
251
-	n, ok := obj.(nodeEntry)
252
-	if !ok {
253
-		panic("unexpected type passed to FromObject")
254
-	}
251
+	n := obj.(*api.Node)
255 252
 
256 253
 	// Add the null character as a terminator
257 254
 	return true, []byte(strconv.FormatInt(int64(n.Spec.Membership), 10) + "\x00"), nil
... ...
@@ -2,28 +2,14 @@ package store
2 2
 
3 3
 import (
4 4
 	"github.com/docker/swarmkit/api"
5
-	"github.com/docker/swarmkit/manager/state"
6 5
 	memdb "github.com/hashicorp/go-memdb"
7 6
 )
8 7
 
9
-// Object is a generic object that can be handled by the store.
10
-type Object interface {
11
-	ID() string               // Get ID
12
-	Meta() api.Meta           // Retrieve metadata
13
-	SetMeta(api.Meta)         // Set metadata
14
-	Copy() Object             // Return a copy of this object
15
-	EventCreate() state.Event // Return a creation event
16
-	EventUpdate() state.Event // Return an update event
17
-	EventDelete() state.Event // Return a deletion event
18
-}
19
-
20 8
 // ObjectStoreConfig provides the necessary methods to store a particular object
21 9
 // type inside MemoryStore.
22 10
 type ObjectStoreConfig struct {
23
-	Name             string
24 11
 	Table            *memdb.TableSchema
25 12
 	Save             func(ReadTx, *api.StoreSnapshot) error
26 13
 	Restore          func(Tx, *api.StoreSnapshot) error
27
-	ApplyStoreAction func(Tx, *api.StoreAction) error
28
-	NewStoreAction   func(state.Event) (api.StoreAction, error)
14
+	ApplyStoreAction func(Tx, api.StoreAction) error
29 15
 }
30 16
new file mode 100644
... ...
@@ -0,0 +1,159 @@
0
+package store
1
+
2
+import (
3
+	"github.com/docker/swarmkit/api"
4
+	memdb "github.com/hashicorp/go-memdb"
5
+	"github.com/pkg/errors"
6
+)
7
+
8
+const tableResource = "resource"
9
+
10
+func init() {
11
+	register(ObjectStoreConfig{
12
+		Table: &memdb.TableSchema{
13
+			Name: tableResource,
14
+			Indexes: map[string]*memdb.IndexSchema{
15
+				indexID: {
16
+					Name:    indexID,
17
+					Unique:  true,
18
+					Indexer: api.ResourceIndexerByID{},
19
+				},
20
+				indexName: {
21
+					Name:    indexName,
22
+					Unique:  true,
23
+					Indexer: api.ResourceIndexerByName{},
24
+				},
25
+				indexKind: {
26
+					Name:    indexKind,
27
+					Indexer: resourceIndexerByKind{},
28
+				},
29
+				indexCustom: {
30
+					Name:         indexCustom,
31
+					Indexer:      api.ResourceCustomIndexer{},
32
+					AllowMissing: true,
33
+				},
34
+			},
35
+		},
36
+		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
37
+			var err error
38
+			snapshot.Resources, err = FindResources(tx, All)
39
+			return err
40
+		},
41
+		Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
42
+			resources, err := FindResources(tx, All)
43
+			if err != nil {
44
+				return err
45
+			}
46
+			for _, r := range resources {
47
+				if err := DeleteResource(tx, r.ID); err != nil {
48
+					return err
49
+				}
50
+			}
51
+			for _, r := range snapshot.Resources {
52
+				if err := CreateResource(tx, r); err != nil {
53
+					return err
54
+				}
55
+			}
56
+			return nil
57
+		},
58
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
59
+			switch v := sa.Target.(type) {
60
+			case *api.StoreAction_Resource:
61
+				obj := v.Resource
62
+				switch sa.Action {
63
+				case api.StoreActionKindCreate:
64
+					return CreateResource(tx, obj)
65
+				case api.StoreActionKindUpdate:
66
+					return UpdateResource(tx, obj)
67
+				case api.StoreActionKindRemove:
68
+					return DeleteResource(tx, obj.ID)
69
+				}
70
+			}
71
+			return errUnknownStoreAction
72
+		},
73
+	})
74
+}
75
+
76
+type resourceEntry struct {
77
+	*api.Resource
78
+}
79
+
80
+func confirmExtension(tx Tx, r *api.Resource) error {
81
+	// There must be an extension corresponding to the Kind field.
82
+	extensions, err := FindExtensions(tx, ByName(r.Kind))
83
+	if err != nil {
84
+		return errors.Wrap(err, "failed to query extensions")
85
+	}
86
+	if len(extensions) == 0 {
87
+		return errors.Errorf("object kind %s is unregistered", r.Kind)
88
+	}
89
+	return nil
90
+}
91
+
92
+// CreateResource adds a new resource object to the store.
93
+// Returns ErrExist if the ID is already taken.
94
+func CreateResource(tx Tx, r *api.Resource) error {
95
+	if err := confirmExtension(tx, r); err != nil {
96
+		return err
97
+	}
98
+	return tx.create(tableResource, resourceEntry{r})
99
+}
100
+
101
+// UpdateResource updates an existing resource object in the store.
102
+// Returns ErrNotExist if the object doesn't exist.
103
+func UpdateResource(tx Tx, r *api.Resource) error {
104
+	if err := confirmExtension(tx, r); err != nil {
105
+		return err
106
+	}
107
+	return tx.update(tableResource, resourceEntry{r})
108
+}
109
+
110
+// DeleteResource removes a resource object from the store.
111
+// Returns ErrNotExist if the object doesn't exist.
112
+func DeleteResource(tx Tx, id string) error {
113
+	return tx.delete(tableResource, id)
114
+}
115
+
116
+// GetResource looks up a resource object by ID.
117
+// Returns nil if the object doesn't exist.
118
+func GetResource(tx ReadTx, id string) *api.Resource {
119
+	r := tx.get(tableResource, id)
120
+	if r == nil {
121
+		return nil
122
+	}
123
+	return r.(resourceEntry).Resource
124
+}
125
+
126
+// FindResources selects a set of resource objects and returns them.
127
+func FindResources(tx ReadTx, by By) ([]*api.Resource, error) {
128
+	checkType := func(by By) error {
129
+		switch by.(type) {
130
+		case byIDPrefix, byName, byKind, byCustom, byCustomPrefix:
131
+			return nil
132
+		default:
133
+			return ErrInvalidFindBy
134
+		}
135
+	}
136
+
137
+	resourceList := []*api.Resource{}
138
+	appendResult := func(o api.StoreObject) {
139
+		resourceList = append(resourceList, o.(resourceEntry).Resource)
140
+	}
141
+
142
+	err := tx.find(tableResource, by, checkType, appendResult)
143
+	return resourceList, err
144
+}
145
+
146
+type resourceIndexerByKind struct{}
147
+
148
+func (ri resourceIndexerByKind) FromArgs(args ...interface{}) ([]byte, error) {
149
+	return fromArgs(args...)
150
+}
151
+
152
+func (ri resourceIndexerByKind) FromObject(obj interface{}) (bool, []byte, error) {
153
+	r := obj.(resourceEntry)
154
+
155
+	// Add the null character as a terminator
156
+	val := r.Resource.Kind + "\x00"
157
+	return true, []byte(val), nil
158
+}
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"strings"
5 5
 
6 6
 	"github.com/docker/swarmkit/api"
7
-	"github.com/docker/swarmkit/manager/state"
8 7
 	memdb "github.com/hashicorp/go-memdb"
9 8
 )
10 9
 
... ...
@@ -12,19 +11,23 @@ const tableSecret = "secret"
12 12
 
13 13
 func init() {
14 14
 	register(ObjectStoreConfig{
15
-		Name: tableSecret,
16 15
 		Table: &memdb.TableSchema{
17 16
 			Name: tableSecret,
18 17
 			Indexes: map[string]*memdb.IndexSchema{
19 18
 				indexID: {
20 19
 					Name:    indexID,
21 20
 					Unique:  true,
22
-					Indexer: secretIndexerByID{},
21
+					Indexer: api.SecretIndexerByID{},
23 22
 				},
24 23
 				indexName: {
25 24
 					Name:    indexName,
26 25
 					Unique:  true,
27
-					Indexer: secretIndexerByName{},
26
+					Indexer: api.SecretIndexerByName{},
27
+				},
28
+				indexCustom: {
29
+					Name:         indexCustom,
30
+					Indexer:      api.SecretCustomIndexer{},
31
+					AllowMissing: true,
28 32
 				},
29 33
 			},
30 34
 		},
... ...
@@ -50,7 +53,7 @@ func init() {
50 50
 			}
51 51
 			return nil
52 52
 		},
53
-		ApplyStoreAction: func(tx Tx, sa *api.StoreAction) error {
53
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
54 54
 			switch v := sa.Target.(type) {
55 55
 			case *api.StoreAction_Secret:
56 56
 				obj := v.Secret
... ...
@@ -65,64 +68,9 @@ func init() {
65 65
 			}
66 66
 			return errUnknownStoreAction
67 67
 		},
68
-		NewStoreAction: func(c state.Event) (api.StoreAction, error) {
69
-			var sa api.StoreAction
70
-			switch v := c.(type) {
71
-			case state.EventCreateSecret:
72
-				sa.Action = api.StoreActionKindCreate
73
-				sa.Target = &api.StoreAction_Secret{
74
-					Secret: v.Secret,
75
-				}
76
-			case state.EventUpdateSecret:
77
-				sa.Action = api.StoreActionKindUpdate
78
-				sa.Target = &api.StoreAction_Secret{
79
-					Secret: v.Secret,
80
-				}
81
-			case state.EventDeleteSecret:
82
-				sa.Action = api.StoreActionKindRemove
83
-				sa.Target = &api.StoreAction_Secret{
84
-					Secret: v.Secret,
85
-				}
86
-			default:
87
-				return api.StoreAction{}, errUnknownStoreAction
88
-			}
89
-			return sa, nil
90
-		},
91 68
 	})
92 69
 }
93 70
 
94
-type secretEntry struct {
95
-	*api.Secret
96
-}
97
-
98
-func (s secretEntry) ID() string {
99
-	return s.Secret.ID
100
-}
101
-
102
-func (s secretEntry) Meta() api.Meta {
103
-	return s.Secret.Meta
104
-}
105
-
106
-func (s secretEntry) SetMeta(meta api.Meta) {
107
-	s.Secret.Meta = meta
108
-}
109
-
110
-func (s secretEntry) Copy() Object {
111
-	return secretEntry{s.Secret.Copy()}
112
-}
113
-
114
-func (s secretEntry) EventCreate() state.Event {
115
-	return state.EventCreateSecret{Secret: s.Secret}
116
-}
117
-
118
-func (s secretEntry) EventUpdate() state.Event {
119
-	return state.EventUpdateSecret{Secret: s.Secret}
120
-}
121
-
122
-func (s secretEntry) EventDelete() state.Event {
123
-	return state.EventDeleteSecret{Secret: s.Secret}
124
-}
125
-
126 71
 // CreateSecret adds a new secret to the store.
127 72
 // Returns ErrExist if the ID is already taken.
128 73
 func CreateSecret(tx Tx, s *api.Secret) error {
... ...
@@ -131,7 +79,7 @@ func CreateSecret(tx Tx, s *api.Secret) error {
131 131
 		return ErrNameConflict
132 132
 	}
133 133
 
134
-	return tx.create(tableSecret, secretEntry{s})
134
+	return tx.create(tableSecret, s)
135 135
 }
136 136
 
137 137
 // UpdateSecret updates an existing secret in the store.
... ...
@@ -139,12 +87,12 @@ func CreateSecret(tx Tx, s *api.Secret) error {
139 139
 func UpdateSecret(tx Tx, s *api.Secret) error {
140 140
 	// Ensure the name is either not in use or already used by this same Secret.
141 141
 	if existing := tx.lookup(tableSecret, indexName, strings.ToLower(s.Spec.Annotations.Name)); existing != nil {
142
-		if existing.ID() != s.ID {
142
+		if existing.GetID() != s.ID {
143 143
 			return ErrNameConflict
144 144
 		}
145 145
 	}
146 146
 
147
-	return tx.update(tableSecret, secretEntry{s})
147
+	return tx.update(tableSecret, s)
148 148
 }
149 149
 
150 150
 // DeleteSecret removes a secret from the store.
... ...
@@ -160,14 +108,14 @@ func GetSecret(tx ReadTx, id string) *api.Secret {
160 160
 	if n == nil {
161 161
 		return nil
162 162
 	}
163
-	return n.(secretEntry).Secret
163
+	return n.(*api.Secret)
164 164
 }
165 165
 
166 166
 // FindSecrets selects a set of secrets and returns them.
167 167
 func FindSecrets(tx ReadTx, by By) ([]*api.Secret, error) {
168 168
 	checkType := func(by By) error {
169 169
 		switch by.(type) {
170
-		case byName, byNamePrefix, byIDPrefix:
170
+		case byName, byNamePrefix, byIDPrefix, byCustom, byCustomPrefix:
171 171
 			return nil
172 172
 		default:
173 173
 			return ErrInvalidFindBy
... ...
@@ -175,51 +123,10 @@ func FindSecrets(tx ReadTx, by By) ([]*api.Secret, error) {
175 175
 	}
176 176
 
177 177
 	secretList := []*api.Secret{}
178
-	appendResult := func(o Object) {
179
-		secretList = append(secretList, o.(secretEntry).Secret)
178
+	appendResult := func(o api.StoreObject) {
179
+		secretList = append(secretList, o.(*api.Secret))
180 180
 	}
181 181
 
182 182
 	err := tx.find(tableSecret, by, checkType, appendResult)
183 183
 	return secretList, err
184 184
 }
185
-
186
-type secretIndexerByID struct{}
187
-
188
-func (ci secretIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
189
-	return fromArgs(args...)
190
-}
191
-
192
-func (ci secretIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
193
-	s, ok := obj.(secretEntry)
194
-	if !ok {
195
-		panic("unexpected type passed to FromObject")
196
-	}
197
-
198
-	// Add the null character as a terminator
199
-	val := s.Secret.ID + "\x00"
200
-	return true, []byte(val), nil
201
-}
202
-
203
-func (ci secretIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
204
-	return prefixFromArgs(args...)
205
-}
206
-
207
-type secretIndexerByName struct{}
208
-
209
-func (ci secretIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
210
-	return fromArgs(args...)
211
-}
212
-
213
-func (ci secretIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
214
-	s, ok := obj.(secretEntry)
215
-	if !ok {
216
-		panic("unexpected type passed to FromObject")
217
-	}
218
-
219
-	// Add the null character as a terminator
220
-	return true, []byte(strings.ToLower(s.Spec.Annotations.Name) + "\x00"), nil
221
-}
222
-
223
-func (ci secretIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
224
-	return prefixFromArgs(args...)
225
-}
... ...
@@ -4,7 +4,7 @@ import (
4 4
 	"strings"
5 5
 
6 6
 	"github.com/docker/swarmkit/api"
7
-	"github.com/docker/swarmkit/manager/state"
7
+	"github.com/docker/swarmkit/api/naming"
8 8
 	memdb "github.com/hashicorp/go-memdb"
9 9
 )
10 10
 
... ...
@@ -12,19 +12,23 @@ const tableService = "service"
12 12
 
13 13
 func init() {
14 14
 	register(ObjectStoreConfig{
15
-		Name: tableService,
16 15
 		Table: &memdb.TableSchema{
17 16
 			Name: tableService,
18 17
 			Indexes: map[string]*memdb.IndexSchema{
19 18
 				indexID: {
20 19
 					Name:    indexID,
21 20
 					Unique:  true,
22
-					Indexer: serviceIndexerByID{},
21
+					Indexer: api.ServiceIndexerByID{},
23 22
 				},
24 23
 				indexName: {
25 24
 					Name:    indexName,
26 25
 					Unique:  true,
27
-					Indexer: serviceIndexerByName{},
26
+					Indexer: api.ServiceIndexerByName{},
27
+				},
28
+				indexRuntime: {
29
+					Name:         indexRuntime,
30
+					AllowMissing: true,
31
+					Indexer:      serviceIndexerByRuntime{},
28 32
 				},
29 33
 				indexNetwork: {
30 34
 					Name:         indexNetwork,
... ...
@@ -36,6 +40,11 @@ func init() {
36 36
 					AllowMissing: true,
37 37
 					Indexer:      serviceIndexerBySecret{},
38 38
 				},
39
+				indexCustom: {
40
+					Name:         indexCustom,
41
+					Indexer:      api.ServiceCustomIndexer{},
42
+					AllowMissing: true,
43
+				},
39 44
 			},
40 45
 		},
41 46
 		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
... ...
@@ -60,7 +69,7 @@ func init() {
60 60
 			}
61 61
 			return nil
62 62
 		},
63
-		ApplyStoreAction: func(tx Tx, sa *api.StoreAction) error {
63
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
64 64
 			switch v := sa.Target.(type) {
65 65
 			case *api.StoreAction_Service:
66 66
 				obj := v.Service
... ...
@@ -75,64 +84,9 @@ func init() {
75 75
 			}
76 76
 			return errUnknownStoreAction
77 77
 		},
78
-		NewStoreAction: func(c state.Event) (api.StoreAction, error) {
79
-			var sa api.StoreAction
80
-			switch v := c.(type) {
81
-			case state.EventCreateService:
82
-				sa.Action = api.StoreActionKindCreate
83
-				sa.Target = &api.StoreAction_Service{
84
-					Service: v.Service,
85
-				}
86
-			case state.EventUpdateService:
87
-				sa.Action = api.StoreActionKindUpdate
88
-				sa.Target = &api.StoreAction_Service{
89
-					Service: v.Service,
90
-				}
91
-			case state.EventDeleteService:
92
-				sa.Action = api.StoreActionKindRemove
93
-				sa.Target = &api.StoreAction_Service{
94
-					Service: v.Service,
95
-				}
96
-			default:
97
-				return api.StoreAction{}, errUnknownStoreAction
98
-			}
99
-			return sa, nil
100
-		},
101 78
 	})
102 79
 }
103 80
 
104
-type serviceEntry struct {
105
-	*api.Service
106
-}
107
-
108
-func (s serviceEntry) ID() string {
109
-	return s.Service.ID
110
-}
111
-
112
-func (s serviceEntry) Meta() api.Meta {
113
-	return s.Service.Meta
114
-}
115
-
116
-func (s serviceEntry) SetMeta(meta api.Meta) {
117
-	s.Service.Meta = meta
118
-}
119
-
120
-func (s serviceEntry) Copy() Object {
121
-	return serviceEntry{s.Service.Copy()}
122
-}
123
-
124
-func (s serviceEntry) EventCreate() state.Event {
125
-	return state.EventCreateService{Service: s.Service}
126
-}
127
-
128
-func (s serviceEntry) EventUpdate() state.Event {
129
-	return state.EventUpdateService{Service: s.Service}
130
-}
131
-
132
-func (s serviceEntry) EventDelete() state.Event {
133
-	return state.EventDeleteService{Service: s.Service}
134
-}
135
-
136 81
 // CreateService adds a new service to the store.
137 82
 // Returns ErrExist if the ID is already taken.
138 83
 func CreateService(tx Tx, s *api.Service) error {
... ...
@@ -141,7 +95,7 @@ func CreateService(tx Tx, s *api.Service) error {
141 141
 		return ErrNameConflict
142 142
 	}
143 143
 
144
-	return tx.create(tableService, serviceEntry{s})
144
+	return tx.create(tableService, s)
145 145
 }
146 146
 
147 147
 // UpdateService updates an existing service in the store.
... ...
@@ -149,12 +103,12 @@ func CreateService(tx Tx, s *api.Service) error {
149 149
 func UpdateService(tx Tx, s *api.Service) error {
150 150
 	// Ensure the name is either not in use or already used by this same Service.
151 151
 	if existing := tx.lookup(tableService, indexName, strings.ToLower(s.Spec.Annotations.Name)); existing != nil {
152
-		if existing.ID() != s.ID {
152
+		if existing.GetID() != s.ID {
153 153
 			return ErrNameConflict
154 154
 		}
155 155
 	}
156 156
 
157
-	return tx.update(tableService, serviceEntry{s})
157
+	return tx.update(tableService, s)
158 158
 }
159 159
 
160 160
 // DeleteService removes a service from the store.
... ...
@@ -170,14 +124,14 @@ func GetService(tx ReadTx, id string) *api.Service {
170 170
 	if s == nil {
171 171
 		return nil
172 172
 	}
173
-	return s.(serviceEntry).Service
173
+	return s.(*api.Service)
174 174
 }
175 175
 
176 176
 // FindServices selects a set of services and returns them.
177 177
 func FindServices(tx ReadTx, by By) ([]*api.Service, error) {
178 178
 	checkType := func(by By) error {
179 179
 		switch by.(type) {
180
-		case byName, byNamePrefix, byIDPrefix, byReferencedNetworkID, byReferencedSecretID:
180
+		case byName, byNamePrefix, byIDPrefix, byRuntime, byReferencedNetworkID, byReferencedSecretID, byCustom, byCustomPrefix:
181 181
 			return nil
182 182
 		default:
183 183
 			return ErrInvalidFindBy
... ...
@@ -185,52 +139,30 @@ func FindServices(tx ReadTx, by By) ([]*api.Service, error) {
185 185
 	}
186 186
 
187 187
 	serviceList := []*api.Service{}
188
-	appendResult := func(o Object) {
189
-		serviceList = append(serviceList, o.(serviceEntry).Service)
188
+	appendResult := func(o api.StoreObject) {
189
+		serviceList = append(serviceList, o.(*api.Service))
190 190
 	}
191 191
 
192 192
 	err := tx.find(tableService, by, checkType, appendResult)
193 193
 	return serviceList, err
194 194
 }
195 195
 
196
-type serviceIndexerByID struct{}
197
-
198
-func (si serviceIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
199
-	return fromArgs(args...)
200
-}
201
-
202
-func (si serviceIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
203
-	s, ok := obj.(serviceEntry)
204
-	if !ok {
205
-		panic("unexpected type passed to FromObject")
206
-	}
207
-
208
-	// Add the null character as a terminator
209
-	val := s.Service.ID + "\x00"
210
-	return true, []byte(val), nil
211
-}
212
-
213
-func (si serviceIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
214
-	return prefixFromArgs(args...)
215
-}
216
-
217
-type serviceIndexerByName struct{}
196
+type serviceIndexerByRuntime struct{}
218 197
 
219
-func (si serviceIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
198
+func (si serviceIndexerByRuntime) FromArgs(args ...interface{}) ([]byte, error) {
220 199
 	return fromArgs(args...)
221 200
 }
222 201
 
223
-func (si serviceIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
224
-	s, ok := obj.(serviceEntry)
225
-	if !ok {
226
-		panic("unexpected type passed to FromObject")
202
+func (si serviceIndexerByRuntime) FromObject(obj interface{}) (bool, []byte, error) {
203
+	s := obj.(*api.Service)
204
+	r, err := naming.Runtime(s.Spec.Task)
205
+	if err != nil {
206
+		return false, nil, nil
227 207
 	}
228
-
229
-	// Add the null character as a terminator
230
-	return true, []byte(strings.ToLower(s.Spec.Annotations.Name) + "\x00"), nil
208
+	return true, []byte(r + "\x00"), nil
231 209
 }
232 210
 
233
-func (si serviceIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
211
+func (si serviceIndexerByRuntime) PrefixFromArgs(args ...interface{}) ([]byte, error) {
234 212
 	return prefixFromArgs(args...)
235 213
 }
236 214
 
... ...
@@ -241,10 +173,7 @@ func (si serviceIndexerByNetwork) FromArgs(args ...interface{}) ([]byte, error)
241 241
 }
242 242
 
243 243
 func (si serviceIndexerByNetwork) FromObject(obj interface{}) (bool, [][]byte, error) {
244
-	s, ok := obj.(serviceEntry)
245
-	if !ok {
246
-		panic("unexpected type passed to FromObject")
247
-	}
244
+	s := obj.(*api.Service)
248 245
 
249 246
 	var networkIDs [][]byte
250 247
 
... ...
@@ -269,10 +198,7 @@ func (si serviceIndexerBySecret) FromArgs(args ...interface{}) ([]byte, error) {
269 269
 }
270 270
 
271 271
 func (si serviceIndexerBySecret) FromObject(obj interface{}) (bool, [][]byte, error) {
272
-	s, ok := obj.(serviceEntry)
273
-	if !ok {
274
-		panic("unexpected type passed to FromObject")
275
-	}
272
+	s := obj.(*api.Service)
276 273
 
277 274
 	container := s.Spec.Task.GetContainer()
278 275
 	if container == nil {
... ...
@@ -6,7 +6,6 @@ import (
6 6
 
7 7
 	"github.com/docker/swarmkit/api"
8 8
 	"github.com/docker/swarmkit/api/naming"
9
-	"github.com/docker/swarmkit/manager/state"
10 9
 	memdb "github.com/hashicorp/go-memdb"
11 10
 )
12 11
 
... ...
@@ -14,20 +13,24 @@ const tableTask = "task"
14 14
 
15 15
 func init() {
16 16
 	register(ObjectStoreConfig{
17
-		Name: tableTask,
18 17
 		Table: &memdb.TableSchema{
19 18
 			Name: tableTask,
20 19
 			Indexes: map[string]*memdb.IndexSchema{
21 20
 				indexID: {
22 21
 					Name:    indexID,
23 22
 					Unique:  true,
24
-					Indexer: taskIndexerByID{},
23
+					Indexer: api.TaskIndexerByID{},
25 24
 				},
26 25
 				indexName: {
27 26
 					Name:         indexName,
28 27
 					AllowMissing: true,
29 28
 					Indexer:      taskIndexerByName{},
30 29
 				},
30
+				indexRuntime: {
31
+					Name:         indexRuntime,
32
+					AllowMissing: true,
33
+					Indexer:      taskIndexerByRuntime{},
34
+				},
31 35
 				indexServiceID: {
32 36
 					Name:         indexServiceID,
33 37
 					AllowMissing: true,
... ...
@@ -61,6 +64,11 @@ func init() {
61 61
 					AllowMissing: true,
62 62
 					Indexer:      taskIndexerBySecret{},
63 63
 				},
64
+				indexCustom: {
65
+					Name:         indexCustom,
66
+					Indexer:      api.TaskCustomIndexer{},
67
+					AllowMissing: true,
68
+				},
64 69
 			},
65 70
 		},
66 71
 		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
... ...
@@ -85,7 +93,7 @@ func init() {
85 85
 			}
86 86
 			return nil
87 87
 		},
88
-		ApplyStoreAction: func(tx Tx, sa *api.StoreAction) error {
88
+		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
89 89
 			switch v := sa.Target.(type) {
90 90
 			case *api.StoreAction_Task:
91 91
 				obj := v.Task
... ...
@@ -100,74 +108,19 @@ func init() {
100 100
 			}
101 101
 			return errUnknownStoreAction
102 102
 		},
103
-		NewStoreAction: func(c state.Event) (api.StoreAction, error) {
104
-			var sa api.StoreAction
105
-			switch v := c.(type) {
106
-			case state.EventCreateTask:
107
-				sa.Action = api.StoreActionKindCreate
108
-				sa.Target = &api.StoreAction_Task{
109
-					Task: v.Task,
110
-				}
111
-			case state.EventUpdateTask:
112
-				sa.Action = api.StoreActionKindUpdate
113
-				sa.Target = &api.StoreAction_Task{
114
-					Task: v.Task,
115
-				}
116
-			case state.EventDeleteTask:
117
-				sa.Action = api.StoreActionKindRemove
118
-				sa.Target = &api.StoreAction_Task{
119
-					Task: v.Task,
120
-				}
121
-			default:
122
-				return api.StoreAction{}, errUnknownStoreAction
123
-			}
124
-			return sa, nil
125
-		},
126 103
 	})
127 104
 }
128 105
 
129
-type taskEntry struct {
130
-	*api.Task
131
-}
132
-
133
-func (t taskEntry) ID() string {
134
-	return t.Task.ID
135
-}
136
-
137
-func (t taskEntry) Meta() api.Meta {
138
-	return t.Task.Meta
139
-}
140
-
141
-func (t taskEntry) SetMeta(meta api.Meta) {
142
-	t.Task.Meta = meta
143
-}
144
-
145
-func (t taskEntry) Copy() Object {
146
-	return taskEntry{t.Task.Copy()}
147
-}
148
-
149
-func (t taskEntry) EventCreate() state.Event {
150
-	return state.EventCreateTask{Task: t.Task}
151
-}
152
-
153
-func (t taskEntry) EventUpdate() state.Event {
154
-	return state.EventUpdateTask{Task: t.Task}
155
-}
156
-
157
-func (t taskEntry) EventDelete() state.Event {
158
-	return state.EventDeleteTask{Task: t.Task}
159
-}
160
-
161 106
 // CreateTask adds a new task to the store.
162 107
 // Returns ErrExist if the ID is already taken.
163 108
 func CreateTask(tx Tx, t *api.Task) error {
164
-	return tx.create(tableTask, taskEntry{t})
109
+	return tx.create(tableTask, t)
165 110
 }
166 111
 
167 112
 // UpdateTask updates an existing task in the store.
168 113
 // Returns ErrNotExist if the node doesn't exist.
169 114
 func UpdateTask(tx Tx, t *api.Task) error {
170
-	return tx.update(tableTask, taskEntry{t})
115
+	return tx.update(tableTask, t)
171 116
 }
172 117
 
173 118
 // DeleteTask removes a task from the store.
... ...
@@ -183,14 +136,14 @@ func GetTask(tx ReadTx, id string) *api.Task {
183 183
 	if t == nil {
184 184
 		return nil
185 185
 	}
186
-	return t.(taskEntry).Task
186
+	return t.(*api.Task)
187 187
 }
188 188
 
189 189
 // FindTasks selects a set of tasks and returns them.
190 190
 func FindTasks(tx ReadTx, by By) ([]*api.Task, error) {
191 191
 	checkType := func(by By) error {
192 192
 		switch by.(type) {
193
-		case byName, byNamePrefix, byIDPrefix, byDesiredState, byTaskState, byNode, byService, bySlot, byReferencedNetworkID, byReferencedSecretID:
193
+		case byName, byNamePrefix, byIDPrefix, byRuntime, byDesiredState, byTaskState, byNode, byService, bySlot, byReferencedNetworkID, byReferencedSecretID, byCustom, byCustomPrefix:
194 194
 			return nil
195 195
 		default:
196 196
 			return ErrInvalidFindBy
... ...
@@ -198,54 +151,49 @@ func FindTasks(tx ReadTx, by By) ([]*api.Task, error) {
198 198
 	}
199 199
 
200 200
 	taskList := []*api.Task{}
201
-	appendResult := func(o Object) {
202
-		taskList = append(taskList, o.(taskEntry).Task)
201
+	appendResult := func(o api.StoreObject) {
202
+		taskList = append(taskList, o.(*api.Task))
203 203
 	}
204 204
 
205 205
 	err := tx.find(tableTask, by, checkType, appendResult)
206 206
 	return taskList, err
207 207
 }
208 208
 
209
-type taskIndexerByID struct{}
209
+type taskIndexerByName struct{}
210 210
 
211
-func (ti taskIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
211
+func (ti taskIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
212 212
 	return fromArgs(args...)
213 213
 }
214 214
 
215
-func (ti taskIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
216
-	t, ok := obj.(taskEntry)
217
-	if !ok {
218
-		panic("unexpected type passed to FromObject")
219
-	}
215
+func (ti taskIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
216
+	t := obj.(*api.Task)
217
+
218
+	name := naming.Task(t)
220 219
 
221 220
 	// Add the null character as a terminator
222
-	val := t.Task.ID + "\x00"
223
-	return true, []byte(val), nil
221
+	return true, []byte(strings.ToLower(name) + "\x00"), nil
224 222
 }
225 223
 
226
-func (ti taskIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
224
+func (ti taskIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
227 225
 	return prefixFromArgs(args...)
228 226
 }
229 227
 
230
-type taskIndexerByName struct{}
228
+type taskIndexerByRuntime struct{}
231 229
 
232
-func (ti taskIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
230
+func (ti taskIndexerByRuntime) FromArgs(args ...interface{}) ([]byte, error) {
233 231
 	return fromArgs(args...)
234 232
 }
235 233
 
236
-func (ti taskIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
237
-	t, ok := obj.(taskEntry)
238
-	if !ok {
239
-		panic("unexpected type passed to FromObject")
234
+func (ti taskIndexerByRuntime) FromObject(obj interface{}) (bool, []byte, error) {
235
+	t := obj.(*api.Task)
236
+	r, err := naming.Runtime(t.Spec)
237
+	if err != nil {
238
+		return false, nil, nil
240 239
 	}
241
-
242
-	name := naming.Task(t.Task)
243
-
244
-	// Add the null character as a terminator
245
-	return true, []byte(strings.ToLower(name) + "\x00"), nil
240
+	return true, []byte(r + "\x00"), nil
246 241
 }
247 242
 
248
-func (ti taskIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
243
+func (ti taskIndexerByRuntime) PrefixFromArgs(args ...interface{}) ([]byte, error) {
249 244
 	return prefixFromArgs(args...)
250 245
 }
251 246
 
... ...
@@ -256,10 +204,7 @@ func (ti taskIndexerByServiceID) FromArgs(args ...interface{}) ([]byte, error) {
256 256
 }
257 257
 
258 258
 func (ti taskIndexerByServiceID) FromObject(obj interface{}) (bool, []byte, error) {
259
-	t, ok := obj.(taskEntry)
260
-	if !ok {
261
-		panic("unexpected type passed to FromObject")
262
-	}
259
+	t := obj.(*api.Task)
263 260
 
264 261
 	// Add the null character as a terminator
265 262
 	val := t.ServiceID + "\x00"
... ...
@@ -273,10 +218,7 @@ func (ti taskIndexerByNodeID) FromArgs(args ...interface{}) ([]byte, error) {
273 273
 }
274 274
 
275 275
 func (ti taskIndexerByNodeID) FromObject(obj interface{}) (bool, []byte, error) {
276
-	t, ok := obj.(taskEntry)
277
-	if !ok {
278
-		panic("unexpected type passed to FromObject")
279
-	}
276
+	t := obj.(*api.Task)
280 277
 
281 278
 	// Add the null character as a terminator
282 279
 	val := t.NodeID + "\x00"
... ...
@@ -290,10 +232,7 @@ func (ti taskIndexerBySlot) FromArgs(args ...interface{}) ([]byte, error) {
290 290
 }
291 291
 
292 292
 func (ti taskIndexerBySlot) FromObject(obj interface{}) (bool, []byte, error) {
293
-	t, ok := obj.(taskEntry)
294
-	if !ok {
295
-		panic("unexpected type passed to FromObject")
296
-	}
293
+	t := obj.(*api.Task)
297 294
 
298 295
 	// Add the null character as a terminator
299 296
 	val := t.ServiceID + "\x00" + strconv.FormatUint(t.Slot, 10) + "\x00"
... ...
@@ -307,10 +246,7 @@ func (ti taskIndexerByDesiredState) FromArgs(args ...interface{}) ([]byte, error
307 307
 }
308 308
 
309 309
 func (ti taskIndexerByDesiredState) FromObject(obj interface{}) (bool, []byte, error) {
310
-	t, ok := obj.(taskEntry)
311
-	if !ok {
312
-		panic("unexpected type passed to FromObject")
313
-	}
310
+	t := obj.(*api.Task)
314 311
 
315 312
 	// Add the null character as a terminator
316 313
 	return true, []byte(strconv.FormatInt(int64(t.DesiredState), 10) + "\x00"), nil
... ...
@@ -323,10 +259,7 @@ func (ti taskIndexerByNetwork) FromArgs(args ...interface{}) ([]byte, error) {
323 323
 }
324 324
 
325 325
 func (ti taskIndexerByNetwork) FromObject(obj interface{}) (bool, [][]byte, error) {
326
-	t, ok := obj.(taskEntry)
327
-	if !ok {
328
-		panic("unexpected type passed to FromObject")
329
-	}
326
+	t := obj.(*api.Task)
330 327
 
331 328
 	var networkIDs [][]byte
332 329
 
... ...
@@ -345,10 +278,7 @@ func (ti taskIndexerBySecret) FromArgs(args ...interface{}) ([]byte, error) {
345 345
 }
346 346
 
347 347
 func (ti taskIndexerBySecret) FromObject(obj interface{}) (bool, [][]byte, error) {
348
-	t, ok := obj.(taskEntry)
349
-	if !ok {
350
-		panic("unexpected type passed to FromObject")
351
-	}
348
+	t := obj.(*api.Task)
352 349
 
353 350
 	container := t.Spec.GetContainer()
354 351
 	if container == nil {
... ...
@@ -372,10 +302,7 @@ func (ts taskIndexerByTaskState) FromArgs(args ...interface{}) ([]byte, error) {
372 372
 }
373 373
 
374 374
 func (ts taskIndexerByTaskState) FromObject(obj interface{}) (bool, []byte, error) {
375
-	t, ok := obj.(taskEntry)
376
-	if !ok {
377
-		panic("unexpected type passed to FromObject")
378
-	}
375
+	t := obj.(*api.Task)
379 376
 
380 377
 	// Add the null character as a terminator
381 378
 	return true, []byte(strconv.FormatInt(int64(t.Status.State), 10) + "\x00"), nil
... ...
@@ -6,30 +6,15 @@ import (
6 6
 	"github.com/docker/swarmkit/watch"
7 7
 )
8 8
 
9
-// Event is the type used for events passed over watcher channels, and also
10
-// the type used to specify filtering in calls to Watch.
11
-type Event interface {
12
-	// TODO(stevvooe): Consider whether it makes sense to squish both the
13
-	// matcher type and the primary type into the same type. It might be better
14
-	// to build a matcher from an event prototype.
15
-
16
-	// matches checks if this item in a watch queue matches the event
17
-	// description.
18
-	matches(events.Event) bool
19
-}
20
-
21 9
 // EventCommit delineates a transaction boundary.
22 10
 type EventCommit struct{}
23 11
 
24
-func (e EventCommit) matches(watchEvent events.Event) bool {
12
+// Matches returns true if this event is a commit event.
13
+func (e EventCommit) Matches(watchEvent events.Event) bool {
25 14
 	_, ok := watchEvent.(EventCommit)
26 15
 	return ok
27 16
 }
28 17
 
29
-// TaskCheckFunc is the type of function used to perform filtering checks on
30
-// api.Task structures.
31
-type TaskCheckFunc func(t1, t2 *api.Task) bool
32
-
33 18
 // TaskCheckID is a TaskCheckFunc for matching task IDs.
34 19
 func TaskCheckID(t1, t2 *api.Task) bool {
35 20
 	return t1.ID == t2.ID
... ...
@@ -50,244 +35,16 @@ func TaskCheckStateGreaterThan(t1, t2 *api.Task) bool {
50 50
 	return t2.Status.State > t1.Status.State
51 51
 }
52 52
 
53
-// EventCreateTask is the type used to put CreateTask events on the
54
-// publish/subscribe queue and filter these events in calls to Watch.
55
-type EventCreateTask struct {
56
-	Task *api.Task
57
-	// Checks is a list of functions to call to filter events for a watch
58
-	// stream. They are applied with AND logic. They are only applicable for
59
-	// calls to Watch.
60
-	Checks []TaskCheckFunc
61
-}
62
-
63
-func (e EventCreateTask) matches(watchEvent events.Event) bool {
64
-	typedEvent, ok := watchEvent.(EventCreateTask)
65
-	if !ok {
66
-		return false
67
-	}
68
-
69
-	for _, check := range e.Checks {
70
-		if !check(e.Task, typedEvent.Task) {
71
-			return false
72
-		}
73
-	}
74
-	return true
75
-}
76
-
77
-// EventUpdateTask is the type used to put UpdateTask events on the
78
-// publish/subscribe queue and filter these events in calls to Watch.
79
-type EventUpdateTask struct {
80
-	Task *api.Task
81
-	// Checks is a list of functions to call to filter events for a watch
82
-	// stream. They are applied with AND logic. They are only applicable for
83
-	// calls to Watch.
84
-	Checks []TaskCheckFunc
85
-}
86
-
87
-func (e EventUpdateTask) matches(watchEvent events.Event) bool {
88
-	typedEvent, ok := watchEvent.(EventUpdateTask)
89
-	if !ok {
90
-		return false
91
-	}
92
-
93
-	for _, check := range e.Checks {
94
-		if !check(e.Task, typedEvent.Task) {
95
-			return false
96
-		}
97
-	}
98
-	return true
99
-}
100
-
101
-// EventDeleteTask is the type used to put DeleteTask events on the
102
-// publish/subscribe queue and filter these events in calls to Watch.
103
-type EventDeleteTask struct {
104
-	Task *api.Task
105
-	// Checks is a list of functions to call to filter events for a watch
106
-	// stream. They are applied with AND logic. They are only applicable for
107
-	// calls to Watch.
108
-	Checks []TaskCheckFunc
109
-}
110
-
111
-func (e EventDeleteTask) matches(watchEvent events.Event) bool {
112
-	typedEvent, ok := watchEvent.(EventDeleteTask)
113
-	if !ok {
114
-		return false
115
-	}
116
-
117
-	for _, check := range e.Checks {
118
-		if !check(e.Task, typedEvent.Task) {
119
-			return false
120
-		}
121
-	}
122
-	return true
123
-}
124
-
125
-// ServiceCheckFunc is the type of function used to perform filtering checks on
126
-// api.Service structures.
127
-type ServiceCheckFunc func(j1, j2 *api.Service) bool
128
-
129 53
 // ServiceCheckID is a ServiceCheckFunc for matching service IDs.
130 54
 func ServiceCheckID(j1, j2 *api.Service) bool {
131 55
 	return j1.ID == j2.ID
132 56
 }
133 57
 
134
-// EventCreateService is the type used to put CreateService events on the
135
-// publish/subscribe queue and filter these events in calls to Watch.
136
-type EventCreateService struct {
137
-	Service *api.Service
138
-	// Checks is a list of functions to call to filter events for a watch
139
-	// stream. They are applied with AND logic. They are only applicable for
140
-	// calls to Watch.
141
-	Checks []ServiceCheckFunc
142
-}
143
-
144
-func (e EventCreateService) matches(watchEvent events.Event) bool {
145
-	typedEvent, ok := watchEvent.(EventCreateService)
146
-	if !ok {
147
-		return false
148
-	}
149
-
150
-	for _, check := range e.Checks {
151
-		if !check(e.Service, typedEvent.Service) {
152
-			return false
153
-		}
154
-	}
155
-	return true
156
-}
157
-
158
-// EventUpdateService is the type used to put UpdateService events on the
159
-// publish/subscribe queue and filter these events in calls to Watch.
160
-type EventUpdateService struct {
161
-	Service *api.Service
162
-	// Checks is a list of functions to call to filter events for a watch
163
-	// stream. They are applied with AND logic. They are only applicable for
164
-	// calls to Watch.
165
-	Checks []ServiceCheckFunc
166
-}
167
-
168
-func (e EventUpdateService) matches(watchEvent events.Event) bool {
169
-	typedEvent, ok := watchEvent.(EventUpdateService)
170
-	if !ok {
171
-		return false
172
-	}
173
-
174
-	for _, check := range e.Checks {
175
-		if !check(e.Service, typedEvent.Service) {
176
-			return false
177
-		}
178
-	}
179
-	return true
180
-}
181
-
182
-// EventDeleteService is the type used to put DeleteService events on the
183
-// publish/subscribe queue and filter these events in calls to Watch.
184
-type EventDeleteService struct {
185
-	Service *api.Service
186
-	// Checks is a list of functions to call to filter events for a watch
187
-	// stream. They are applied with AND logic. They are only applicable for
188
-	// calls to Watch.
189
-	Checks []ServiceCheckFunc
190
-}
191
-
192
-func (e EventDeleteService) matches(watchEvent events.Event) bool {
193
-	typedEvent, ok := watchEvent.(EventDeleteService)
194
-	if !ok {
195
-		return false
196
-	}
197
-
198
-	for _, check := range e.Checks {
199
-		if !check(e.Service, typedEvent.Service) {
200
-			return false
201
-		}
202
-	}
203
-	return true
204
-}
205
-
206
-// NetworkCheckFunc is the type of function used to perform filtering checks on
207
-// api.Service structures.
208
-type NetworkCheckFunc func(n1, n2 *api.Network) bool
209
-
210 58
 // NetworkCheckID is a NetworkCheckFunc for matching network IDs.
211 59
 func NetworkCheckID(n1, n2 *api.Network) bool {
212 60
 	return n1.ID == n2.ID
213 61
 }
214 62
 
215
-// EventCreateNetwork is the type used to put CreateNetwork events on the
216
-// publish/subscribe queue and filter these events in calls to Watch.
217
-type EventCreateNetwork struct {
218
-	Network *api.Network
219
-	// Checks is a list of functions to call to filter events for a watch
220
-	// stream. They are applied with AND logic. They are only applicable for
221
-	// calls to Watch.
222
-	Checks []NetworkCheckFunc
223
-}
224
-
225
-func (e EventCreateNetwork) matches(watchEvent events.Event) bool {
226
-	typedEvent, ok := watchEvent.(EventCreateNetwork)
227
-	if !ok {
228
-		return false
229
-	}
230
-
231
-	for _, check := range e.Checks {
232
-		if !check(e.Network, typedEvent.Network) {
233
-			return false
234
-		}
235
-	}
236
-	return true
237
-}
238
-
239
-// EventUpdateNetwork is the type used to put UpdateNetwork events on the
240
-// publish/subscribe queue and filter these events in calls to Watch.
241
-type EventUpdateNetwork struct {
242
-	Network *api.Network
243
-	// Checks is a list of functions to call to filter events for a watch
244
-	// stream. They are applied with AND logic. They are only applicable for
245
-	// calls to Watch.
246
-	Checks []NetworkCheckFunc
247
-}
248
-
249
-func (e EventUpdateNetwork) matches(watchEvent events.Event) bool {
250
-	typedEvent, ok := watchEvent.(EventUpdateNetwork)
251
-	if !ok {
252
-		return false
253
-	}
254
-
255
-	for _, check := range e.Checks {
256
-		if !check(e.Network, typedEvent.Network) {
257
-			return false
258
-		}
259
-	}
260
-	return true
261
-}
262
-
263
-// EventDeleteNetwork is the type used to put DeleteNetwork events on the
264
-// publish/subscribe queue and filter these events in calls to Watch.
265
-type EventDeleteNetwork struct {
266
-	Network *api.Network
267
-	// Checks is a list of functions to call to filter events for a watch
268
-	// stream. They are applied with AND logic. They are only applicable for
269
-	// calls to Watch.
270
-	Checks []NetworkCheckFunc
271
-}
272
-
273
-func (e EventDeleteNetwork) matches(watchEvent events.Event) bool {
274
-	typedEvent, ok := watchEvent.(EventDeleteNetwork)
275
-	if !ok {
276
-		return false
277
-	}
278
-
279
-	for _, check := range e.Checks {
280
-		if !check(e.Network, typedEvent.Network) {
281
-			return false
282
-		}
283
-	}
284
-	return true
285
-}
286
-
287
-// NodeCheckFunc is the type of function used to perform filtering checks on
288
-// api.Service structures.
289
-type NodeCheckFunc func(n1, n2 *api.Node) bool
290
-
291 63
 // NodeCheckID is a NodeCheckFunc for matching node IDs.
292 64
 func NodeCheckID(n1, n2 *api.Node) bool {
293 65
 	return n1.ID == n2.ID
... ...
@@ -298,238 +55,34 @@ func NodeCheckState(n1, n2 *api.Node) bool {
298 298
 	return n1.Status.State == n2.Status.State
299 299
 }
300 300
 
301
-// EventCreateNode is the type used to put CreateNode events on the
302
-// publish/subscribe queue and filter these events in calls to Watch.
303
-type EventCreateNode struct {
304
-	Node *api.Node
305
-	// Checks is a list of functions to call to filter events for a watch
306
-	// stream. They are applied with AND logic. They are only applicable for
307
-	// calls to Watch.
308
-	Checks []NodeCheckFunc
309
-}
310
-
311
-func (e EventCreateNode) matches(watchEvent events.Event) bool {
312
-	typedEvent, ok := watchEvent.(EventCreateNode)
313
-	if !ok {
314
-		return false
315
-	}
316
-
317
-	for _, check := range e.Checks {
318
-		if !check(e.Node, typedEvent.Node) {
319
-			return false
320
-		}
321
-	}
322
-	return true
323
-}
324
-
325
-// EventUpdateNode is the type used to put DeleteNode events on the
326
-// publish/subscribe queue and filter these events in calls to Watch.
327
-type EventUpdateNode struct {
328
-	Node *api.Node
329
-	// Checks is a list of functions to call to filter events for a watch
330
-	// stream. They are applied with AND logic. They are only applicable for
331
-	// calls to Watch.
332
-	Checks []NodeCheckFunc
333
-}
334
-
335
-func (e EventUpdateNode) matches(watchEvent events.Event) bool {
336
-	typedEvent, ok := watchEvent.(EventUpdateNode)
337
-	if !ok {
338
-		return false
339
-	}
340
-
341
-	for _, check := range e.Checks {
342
-		if !check(e.Node, typedEvent.Node) {
343
-			return false
344
-		}
345
-	}
346
-	return true
347
-}
348
-
349
-// EventDeleteNode is the type used to put DeleteNode events on the
350
-// publish/subscribe queue and filter these events in calls to Watch.
351
-type EventDeleteNode struct {
352
-	Node *api.Node
353
-	// Checks is a list of functions to call to filter events for a watch
354
-	// stream. They are applied with AND logic. They are only applicable for
355
-	// calls to Watch.
356
-	Checks []NodeCheckFunc
357
-}
358
-
359
-func (e EventDeleteNode) matches(watchEvent events.Event) bool {
360
-	typedEvent, ok := watchEvent.(EventDeleteNode)
361
-	if !ok {
362
-		return false
363
-	}
364
-
365
-	for _, check := range e.Checks {
366
-		if !check(e.Node, typedEvent.Node) {
367
-			return false
368
-		}
369
-	}
370
-	return true
371
-}
372
-
373
-// ClusterCheckFunc is the type of function used to perform filtering checks on
374
-// api.Cluster structures.
375
-type ClusterCheckFunc func(v1, v2 *api.Cluster) bool
376
-
377 301
 // ClusterCheckID is a ClusterCheckFunc for matching volume IDs.
378 302
 func ClusterCheckID(v1, v2 *api.Cluster) bool {
379 303
 	return v1.ID == v2.ID
380 304
 }
381 305
 
382
-// EventCreateCluster is the type used to put CreateCluster events on the
383
-// publish/subscribe queue and filter these events in calls to Watch.
384
-type EventCreateCluster struct {
385
-	Cluster *api.Cluster
386
-	// Checks is a list of functions to call to filter events for a watch
387
-	// stream. They are applied with AND logic. They are only applicable for
388
-	// calls to Watch.
389
-	Checks []ClusterCheckFunc
390
-}
391
-
392
-func (e EventCreateCluster) matches(watchEvent events.Event) bool {
393
-	typedEvent, ok := watchEvent.(EventCreateCluster)
394
-	if !ok {
395
-		return false
396
-	}
397
-
398
-	for _, check := range e.Checks {
399
-		if !check(e.Cluster, typedEvent.Cluster) {
400
-			return false
401
-		}
402
-	}
403
-	return true
404
-}
405
-
406
-// EventUpdateCluster is the type used to put UpdateCluster events on the
407
-// publish/subscribe queue and filter these events in calls to Watch.
408
-type EventUpdateCluster struct {
409
-	Cluster *api.Cluster
410
-	// Checks is a list of functions to call to filter events for a watch
411
-	// stream. They are applied with AND logic. They are only applicable for
412
-	// calls to Watch.
413
-	Checks []ClusterCheckFunc
414
-}
415
-
416
-func (e EventUpdateCluster) matches(watchEvent events.Event) bool {
417
-	typedEvent, ok := watchEvent.(EventUpdateCluster)
418
-	if !ok {
419
-		return false
420
-	}
421
-
422
-	for _, check := range e.Checks {
423
-		if !check(e.Cluster, typedEvent.Cluster) {
424
-			return false
425
-		}
426
-	}
427
-	return true
428
-}
429
-
430
-// EventDeleteCluster is the type used to put DeleteCluster events on the
431
-// publish/subscribe queue and filter these events in calls to Watch.
432
-type EventDeleteCluster struct {
433
-	Cluster *api.Cluster
434
-	// Checks is a list of functions to call to filter events for a watch
435
-	// stream. They are applied with AND logic. They are only applicable for
436
-	// calls to Watch.
437
-	Checks []ClusterCheckFunc
438
-}
439
-
440
-func (e EventDeleteCluster) matches(watchEvent events.Event) bool {
441
-	typedEvent, ok := watchEvent.(EventDeleteCluster)
442
-	if !ok {
443
-		return false
444
-	}
445
-
446
-	for _, check := range e.Checks {
447
-		if !check(e.Cluster, typedEvent.Cluster) {
448
-			return false
449
-		}
450
-	}
451
-	return true
452
-}
453
-
454
-// SecretCheckFunc is the type of function used to perform filtering checks on
455
-// api.Secret structures.
456
-type SecretCheckFunc func(v1, v2 *api.Secret) bool
457
-
458
-// SecretCheckID is a SecretCheckFunc for matching volume IDs.
306
+// SecretCheckID is a SecretCheckFunc for matching secret IDs.
459 307
 func SecretCheckID(v1, v2 *api.Secret) bool {
460 308
 	return v1.ID == v2.ID
461 309
 }
462 310
 
463
-// EventCreateSecret is the type used to put CreateSecret events on the
464
-// publish/subscribe queue and filter these events in calls to Watch.
465
-type EventCreateSecret struct {
466
-	Secret *api.Secret
467
-	// Checks is a list of functions to call to filter events for a watch
468
-	// stream. They are applied with AND logic. They are only applicable for
469
-	// calls to Watch.
470
-	Checks []SecretCheckFunc
471
-}
472
-
473
-func (e EventCreateSecret) matches(watchEvent events.Event) bool {
474
-	typedEvent, ok := watchEvent.(EventCreateSecret)
475
-	if !ok {
476
-		return false
477
-	}
478
-
479
-	for _, check := range e.Checks {
480
-		if !check(e.Secret, typedEvent.Secret) {
481
-			return false
482
-		}
483
-	}
484
-	return true
485
-}
486
-
487
-// EventUpdateSecret is the type used to put UpdateSecret events on the
488
-// publish/subscribe queue and filter these events in calls to Watch.
489
-type EventUpdateSecret struct {
490
-	Secret *api.Secret
491
-	// Checks is a list of functions to call to filter events for a watch
492
-	// stream. They are applied with AND logic. They are only applicable for
493
-	// calls to Watch.
494
-	Checks []SecretCheckFunc
311
+// ResourceCheckID is a ResourceCheckFunc for matching resource IDs.
312
+func ResourceCheckID(v1, v2 *api.Resource) bool {
313
+	return v1.ID == v2.ID
495 314
 }
496 315
 
497
-func (e EventUpdateSecret) matches(watchEvent events.Event) bool {
498
-	typedEvent, ok := watchEvent.(EventUpdateSecret)
499
-	if !ok {
500
-		return false
501
-	}
502
-
503
-	for _, check := range e.Checks {
504
-		if !check(e.Secret, typedEvent.Secret) {
505
-			return false
506
-		}
507
-	}
508
-	return true
316
+// ResourceCheckKind is a ResourceCheckFunc for matching resource kinds.
317
+func ResourceCheckKind(v1, v2 *api.Resource) bool {
318
+	return v1.Kind == v2.Kind
509 319
 }
510 320
 
511
-// EventDeleteSecret is the type used to put DeleteSecret events on the
512
-// publish/subscribe queue and filter these events in calls to Watch.
513
-type EventDeleteSecret struct {
514
-	Secret *api.Secret
515
-	// Checks is a list of functions to call to filter events for a watch
516
-	// stream. They are applied with AND logic. They are only applicable for
517
-	// calls to Watch.
518
-	Checks []SecretCheckFunc
321
+// ExtensionCheckID is a ExtensionCheckFunc for matching extension IDs.
322
+func ExtensionCheckID(v1, v2 *api.Extension) bool {
323
+	return v1.ID == v2.ID
519 324
 }
520 325
 
521
-func (e EventDeleteSecret) matches(watchEvent events.Event) bool {
522
-	typedEvent, ok := watchEvent.(EventDeleteSecret)
523
-	if !ok {
524
-		return false
525
-	}
526
-
527
-	for _, check := range e.Checks {
528
-		if !check(e.Secret, typedEvent.Secret) {
529
-			return false
530
-		}
531
-	}
532
-	return true
326
+// ExtensionCheckName is a ExtensionCheckFunc for matching extension names names.
327
+func ExtensionCheckName(v1, v2 *api.Extension) bool {
328
+	return v1.Annotations.Name == v2.Annotations.Name
533 329
 }
534 330
 
535 331
 // Watch takes a variable number of events to match against. The subscriber
... ...
@@ -559,18 +112,18 @@ func (e EventDeleteSecret) matches(watchEvent events.Event) bool {
559 559
 //                                                 func(t1, t2 *api.Task) bool {
560 560
 //                                                         return t1.ServiceID == t2.ServiceID
561 561
 //                                                 }}})
562
-func Watch(queue *watch.Queue, specifiers ...Event) (eventq chan events.Event, cancel func()) {
562
+func Watch(queue *watch.Queue, specifiers ...api.Event) (eventq chan events.Event, cancel func()) {
563 563
 	if len(specifiers) == 0 {
564 564
 		return queue.Watch()
565 565
 	}
566 566
 	return queue.CallbackWatch(Matcher(specifiers...))
567 567
 }
568 568
 
569
-// Matcher returns an events.Matcher that matches the specifiers with OR logic.
570
-func Matcher(specifiers ...Event) events.MatcherFunc {
569
+// Matcher returns an events.Matcher that Matches the specifiers with OR logic.
570
+func Matcher(specifiers ...api.Event) events.MatcherFunc {
571 571
 	return events.MatcherFunc(func(event events.Event) bool {
572 572
 		for _, s := range specifiers {
573
-			if s.matches(event) {
573
+			if s.Matches(event) {
574 574
 				return true
575 575
 			}
576 576
 		}
... ...
@@ -600,10 +600,13 @@ func (n *Node) loadSecurityConfig(ctx context.Context) (*ca.SecurityConfig, erro
600 600
 				n.unlockKey = encryption.GenerateSecretKey()
601 601
 			}
602 602
 			krw = ca.NewKeyReadWriter(paths.Node, n.unlockKey, &manager.RaftDEKData{})
603
-			rootCA, err = ca.CreateRootCA(ca.DefaultRootCN, paths.RootCA)
603
+			rootCA, err = ca.CreateRootCA(ca.DefaultRootCN)
604 604
 			if err != nil {
605 605
 				return nil, err
606 606
 			}
607
+			if err := ca.SaveRootCA(rootCA, paths.RootCA); err != nil {
608
+				return nil, err
609
+			}
607 610
 			log.G(ctx).Debug("generated CA key and certificate")
608 611
 		} else if err == ca.ErrNoLocalRootCA { // from previous error loading the root CA from disk
609 612
 			rootCA, err = ca.DownloadRootCA(ctx, paths.RootCA, n.config.JoinToken, n.connBroker)
... ...
@@ -9,6 +9,7 @@
9 9
 		plugin.proto
10 10
 
11 11
 	It has these top-level messages:
12
+		StoreObject
12 13
 		TLSAuthorization
13 14
 */
14 15
 package plugin
... ...
@@ -34,6 +35,14 @@ var _ = math.Inf
34 34
 // proto package needs to be updated.
35 35
 const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
36 36
 
37
+type StoreObject struct {
38
+	XXX_unrecognized []byte `json:"-"`
39
+}
40
+
41
+func (m *StoreObject) Reset()                    { *m = StoreObject{} }
42
+func (*StoreObject) ProtoMessage()               {}
43
+func (*StoreObject) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{0} }
44
+
37 45
 type TLSAuthorization struct {
38 46
 	// Roles contains the acceptable TLS OU roles for the handler.
39 47
 	Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"`
... ...
@@ -46,7 +55,7 @@ type TLSAuthorization struct {
46 46
 
47 47
 func (m *TLSAuthorization) Reset()                    { *m = TLSAuthorization{} }
48 48
 func (*TLSAuthorization) ProtoMessage()               {}
49
-func (*TLSAuthorization) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{0} }
49
+func (*TLSAuthorization) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{1} }
50 50
 
51 51
 var E_Deepcopy = &proto.ExtensionDesc{
52 52
 	ExtendedType:  (*google_protobuf.MessageOptions)(nil),
... ...
@@ -56,6 +65,14 @@ var E_Deepcopy = &proto.ExtensionDesc{
56 56
 	Tag:           "varint,70000,opt,name=deepcopy,def=1",
57 57
 }
58 58
 
59
+var E_StoreObject = &proto.ExtensionDesc{
60
+	ExtendedType:  (*google_protobuf.MessageOptions)(nil),
61
+	ExtensionType: (*StoreObject)(nil),
62
+	Field:         70001,
63
+	Name:          "docker.protobuf.plugin.store_object",
64
+	Tag:           "bytes,70001,opt,name=store_object,json=storeObject",
65
+}
66
+
59 67
 var E_TlsAuthorization = &proto.ExtensionDesc{
60 68
 	ExtendedType:  (*google_protobuf.MethodOptions)(nil),
61 69
 	ExtensionType: (*TLSAuthorization)(nil),
... ...
@@ -65,10 +82,33 @@ var E_TlsAuthorization = &proto.ExtensionDesc{
65 65
 }
66 66
 
67 67
 func init() {
68
+	proto.RegisterType((*StoreObject)(nil), "docker.protobuf.plugin.StoreObject")
68 69
 	proto.RegisterType((*TLSAuthorization)(nil), "docker.protobuf.plugin.TLSAuthorization")
69 70
 	proto.RegisterExtension(E_Deepcopy)
71
+	proto.RegisterExtension(E_StoreObject)
70 72
 	proto.RegisterExtension(E_TlsAuthorization)
71 73
 }
74
+func (m *StoreObject) Marshal() (dAtA []byte, err error) {
75
+	size := m.Size()
76
+	dAtA = make([]byte, size)
77
+	n, err := m.MarshalTo(dAtA)
78
+	if err != nil {
79
+		return nil, err
80
+	}
81
+	return dAtA[:n], nil
82
+}
83
+
84
+func (m *StoreObject) MarshalTo(dAtA []byte) (int, error) {
85
+	var i int
86
+	_ = i
87
+	var l int
88
+	_ = l
89
+	if m.XXX_unrecognized != nil {
90
+		i += copy(dAtA[i:], m.XXX_unrecognized)
91
+	}
92
+	return i, nil
93
+}
94
+
72 95
 func (m *TLSAuthorization) Marshal() (dAtA []byte, err error) {
73 96
 	size := m.Size()
74 97
 	dAtA = make([]byte, size)
... ...
@@ -142,6 +182,15 @@ func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int {
142 142
 	dAtA[offset] = uint8(v)
143 143
 	return offset + 1
144 144
 }
145
+func (m *StoreObject) Size() (n int) {
146
+	var l int
147
+	_ = l
148
+	if m.XXX_unrecognized != nil {
149
+		n += len(m.XXX_unrecognized)
150
+	}
151
+	return n
152
+}
153
+
145 154
 func (m *TLSAuthorization) Size() (n int) {
146 155
 	var l int
147 156
 	_ = l
... ...
@@ -173,6 +222,16 @@ func sovPlugin(x uint64) (n int) {
173 173
 func sozPlugin(x uint64) (n int) {
174 174
 	return sovPlugin(uint64((x << 1) ^ uint64((int64(x) >> 63))))
175 175
 }
176
+func (this *StoreObject) String() string {
177
+	if this == nil {
178
+		return "nil"
179
+	}
180
+	s := strings.Join([]string{`&StoreObject{`,
181
+		`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
182
+		`}`,
183
+	}, "")
184
+	return s
185
+}
176 186
 func (this *TLSAuthorization) String() string {
177 187
 	if this == nil {
178 188
 		return "nil"
... ...
@@ -193,6 +252,57 @@ func valueToStringPlugin(v interface{}) string {
193 193
 	pv := reflect.Indirect(rv).Interface()
194 194
 	return fmt.Sprintf("*%v", pv)
195 195
 }
196
+func (m *StoreObject) Unmarshal(dAtA []byte) error {
197
+	l := len(dAtA)
198
+	iNdEx := 0
199
+	for iNdEx < l {
200
+		preIndex := iNdEx
201
+		var wire uint64
202
+		for shift := uint(0); ; shift += 7 {
203
+			if shift >= 64 {
204
+				return ErrIntOverflowPlugin
205
+			}
206
+			if iNdEx >= l {
207
+				return io.ErrUnexpectedEOF
208
+			}
209
+			b := dAtA[iNdEx]
210
+			iNdEx++
211
+			wire |= (uint64(b) & 0x7F) << shift
212
+			if b < 0x80 {
213
+				break
214
+			}
215
+		}
216
+		fieldNum := int32(wire >> 3)
217
+		wireType := int(wire & 0x7)
218
+		if wireType == 4 {
219
+			return fmt.Errorf("proto: StoreObject: wiretype end group for non-group")
220
+		}
221
+		if fieldNum <= 0 {
222
+			return fmt.Errorf("proto: StoreObject: illegal tag %d (wire type %d)", fieldNum, wire)
223
+		}
224
+		switch fieldNum {
225
+		default:
226
+			iNdEx = preIndex
227
+			skippy, err := skipPlugin(dAtA[iNdEx:])
228
+			if err != nil {
229
+				return err
230
+			}
231
+			if skippy < 0 {
232
+				return ErrInvalidLengthPlugin
233
+			}
234
+			if (iNdEx + skippy) > l {
235
+				return io.ErrUnexpectedEOF
236
+			}
237
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
238
+			iNdEx += skippy
239
+		}
240
+	}
241
+
242
+	if iNdEx > l {
243
+		return io.ErrUnexpectedEOF
244
+	}
245
+	return nil
246
+}
196 247
 func (m *TLSAuthorization) Unmarshal(dAtA []byte) error {
197 248
 	l := len(dAtA)
198 249
 	iNdEx := 0
... ...
@@ -402,21 +512,24 @@ var (
402 402
 func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) }
403 403
 
404 404
 var fileDescriptorPlugin = []byte{
405
-	// 254 bytes of a gzipped FileDescriptorProto
405
+	// 296 bytes of a gzipped FileDescriptorProto
406 406
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d,
407 407
 	0xcf, 0xcc, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4b, 0xc9, 0x4f, 0xce, 0x4e, 0x2d,
408 408
 	0x82, 0xf0, 0x92, 0x4a, 0xd3, 0xf4, 0x20, 0xb2, 0x52, 0x0a, 0xe9, 0xf9, 0xf9, 0xe9, 0x39, 0xa9,
409 409
 	0xfa, 0x30, 0x71, 0xfd, 0x94, 0xd4, 0xe2, 0xe4, 0xa2, 0xcc, 0x82, 0x92, 0x7c, 0xa8, 0x5a, 0x25,
410
-	0x17, 0x2e, 0x81, 0x10, 0x9f, 0x60, 0xc7, 0xd2, 0x92, 0x8c, 0xfc, 0xa2, 0xcc, 0xaa, 0xc4, 0x92,
411
-	0xcc, 0xfc, 0x3c, 0x21, 0x11, 0x2e, 0xd6, 0xa2, 0xfc, 0x9c, 0xd4, 0x62, 0x09, 0x46, 0x05, 0x66,
412
-	0x0d, 0xce, 0x20, 0x08, 0x47, 0x48, 0x8a, 0x8b, 0x23, 0x33, 0xaf, 0x38, 0x35, 0xb9, 0xb4, 0x28,
413
-	0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0x23, 0x08, 0xce, 0xb7, 0x72, 0xe6, 0xe2, 0x48, 0x49, 0x4d,
414
-	0x2d, 0x48, 0xce, 0x2f, 0xa8, 0x14, 0x92, 0xd7, 0x83, 0x58, 0x8a, 0x70, 0x8c, 0x6f, 0x6a, 0x71,
415
-	0x71, 0x62, 0x7a, 0xaa, 0x7f, 0x01, 0xc8, 0xf4, 0x62, 0x89, 0x0f, 0x8b, 0x58, 0x40, 0xda, 0xad,
416
-	0x58, 0x4a, 0x8a, 0x4a, 0x53, 0x83, 0xe0, 0x1a, 0xad, 0x2a, 0xb8, 0x04, 0x4b, 0x72, 0x8a, 0xe3,
417
-	0x13, 0x51, 0xdc, 0x22, 0x87, 0xc5, 0xb4, 0x92, 0x8c, 0xfc, 0x14, 0x98, 0x61, 0x2f, 0x9f, 0xf6,
418
-	0x2a, 0x2b, 0x30, 0x6a, 0x70, 0x1b, 0x69, 0xe8, 0x61, 0x0f, 0x03, 0x3d, 0x74, 0xef, 0x05, 0x09,
419
-	0x94, 0xe4, 0x14, 0xa3, 0x88, 0x38, 0x49, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43,
420
-	0xc3, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e,
421
-	0x11, 0x10, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x4c, 0x2c, 0xf3, 0x67, 0x01, 0x00, 0x00,
410
+	0x5e, 0x2e, 0xee, 0xe0, 0x92, 0xfc, 0xa2, 0x54, 0xff, 0xa4, 0xac, 0xd4, 0xe4, 0x12, 0x25, 0x17,
411
+	0x2e, 0x81, 0x10, 0x9f, 0x60, 0xc7, 0xd2, 0x92, 0x8c, 0xfc, 0xa2, 0xcc, 0xaa, 0xc4, 0x92, 0xcc,
412
+	0xfc, 0x3c, 0x21, 0x11, 0x2e, 0xd6, 0xa2, 0xfc, 0x9c, 0xd4, 0x62, 0x09, 0x46, 0x05, 0x66, 0x0d,
413
+	0xce, 0x20, 0x08, 0x47, 0x48, 0x8a, 0x8b, 0x23, 0x33, 0xaf, 0x38, 0x35, 0xb9, 0xb4, 0x28, 0x55,
414
+	0x82, 0x49, 0x81, 0x51, 0x83, 0x23, 0x08, 0xce, 0xb7, 0x72, 0xe6, 0xe2, 0x48, 0x49, 0x4d, 0x2d,
415
+	0x48, 0xce, 0x2f, 0xa8, 0x14, 0x92, 0xd7, 0x83, 0xb8, 0x01, 0xe1, 0x36, 0xdf, 0xd4, 0xe2, 0xe2,
416
+	0xc4, 0xf4, 0x54, 0xff, 0x02, 0x90, 0xe9, 0xc5, 0x12, 0x1f, 0x16, 0xb1, 0x80, 0xb4, 0x5b, 0xb1,
417
+	0x94, 0x14, 0x95, 0xa6, 0x06, 0xc1, 0x35, 0x5a, 0x65, 0x72, 0xf1, 0x14, 0x83, 0x5c, 0x16, 0x9f,
418
+	0x0f, 0x76, 0x1a, 0x61, 0x83, 0x3e, 0x82, 0x0d, 0xe2, 0x36, 0x52, 0xd6, 0xc3, 0x1e, 0x1a, 0x7a,
419
+	0x48, 0x1e, 0x0d, 0xe2, 0x2e, 0x46, 0x70, 0xac, 0x2a, 0xb8, 0x04, 0x4b, 0x72, 0x8a, 0xe3, 0x13,
420
+	0x51, 0xbc, 0x2d, 0x87, 0xc5, 0xbe, 0x92, 0x8c, 0xfc, 0x14, 0x98, 0x75, 0x2f, 0x9f, 0xf6, 0x2a,
421
+	0x83, 0xed, 0xd3, 0xc0, 0x65, 0x1f, 0x7a, 0x48, 0x06, 0x09, 0x94, 0xe4, 0x14, 0xa3, 0x88, 0x38,
422
+	0x49, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6, 0x13, 0x8f,
423
+	0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x11, 0x10, 0x00, 0x00, 0xff, 0xff,
424
+	0xc2, 0x49, 0xd6, 0x3b, 0xe1, 0x01, 0x00, 0x00,
422 425
 }
... ...
@@ -4,8 +4,12 @@ package docker.protobuf.plugin;
4 4
 
5 5
 import "google/protobuf/descriptor.proto";
6 6
 
7
+message StoreObject {
8
+}
9
+
7 10
 extend google.protobuf.MessageOptions {
8 11
 	optional bool deepcopy = 70000 [default=true];
12
+	optional StoreObject store_object = 70001;
9 13
 }
10 14
 
11 15
 message TLSAuthorization {