Browse code

Convert endpoint gossip to use protobuf

Endpoint gossip will use protobuf so that we can make changes in a
backward compatible way.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>

Jana Radhakrishnan authored on 2016/05/18 06:12:39
Showing 3 changed files
... ...
@@ -1,10 +1,11 @@
1 1
 package libnetwork
2 2
 
3
+//go:generate protoc -I.:Godeps/_workspace/src/github.com/gogo/protobuf  --gogo_out=import_path=github.com/docker/libnetwork,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. agent.proto
4
+
3 5
 import (
4 6
 	"fmt"
5 7
 	"net"
6 8
 	"os"
7
-	"strings"
8 9
 
9 10
 	"github.com/Sirupsen/logrus"
10 11
 	"github.com/docker/go-events"
... ...
@@ -12,6 +13,7 @@ import (
12 12
 	"github.com/docker/libnetwork/discoverapi"
13 13
 	"github.com/docker/libnetwork/driverapi"
14 14
 	"github.com/docker/libnetwork/networkdb"
15
+	"github.com/gogo/protobuf/proto"
15 16
 )
16 17
 
17 18
 type agent struct {
... ...
@@ -169,8 +171,18 @@ func (ep *endpoint) addToCluster() error {
169 169
 			return err
170 170
 		}
171 171
 
172
-		if err := c.agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), []byte(fmt.Sprintf("%s,%s,%s,%s", ep.Name(), ep.svcName,
173
-			ep.svcID, ep.Iface().Address().IP))); err != nil {
172
+		buf, err := proto.Marshal(&EndpointRecord{
173
+			Name:        ep.Name(),
174
+			ServiceName: ep.svcName,
175
+			ServiceID:   ep.svcID,
176
+			EndpointIP:  ep.Iface().Address().IP.String(),
177
+		})
178
+
179
+		if err != nil {
180
+			return err
181
+		}
182
+
183
+		if err := c.agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil {
174 184
 			return err
175 185
 		}
176 186
 	}
... ...
@@ -310,20 +322,21 @@ func (c *controller) handleEpTableEvent(ev events.Event) {
310 310
 	var (
311 311
 		nid   string
312 312
 		eid   string
313
-		value string
313
+		value []byte
314 314
 		isAdd bool
315
+		epRec EndpointRecord
315 316
 	)
316 317
 
317 318
 	switch event := ev.(type) {
318 319
 	case networkdb.CreateEvent:
319 320
 		nid = event.NetworkID
320 321
 		eid = event.Key
321
-		value = string(event.Value)
322
+		value = event.Value
322 323
 		isAdd = true
323 324
 	case networkdb.DeleteEvent:
324 325
 		nid = event.NetworkID
325 326
 		eid = event.Key
326
-		value = string(event.Value)
327
+		value = event.Value
327 328
 	case networkdb.UpdateEvent:
328 329
 		logrus.Errorf("Unexpected update service table event = %#v", event)
329 330
 	}
... ...
@@ -335,16 +348,16 @@ func (c *controller) handleEpTableEvent(ev events.Event) {
335 335
 	}
336 336
 	n := nw.(*network)
337 337
 
338
-	vals := strings.Split(value, ",")
339
-	if len(vals) < 4 {
340
-		logrus.Errorf("Incorrect service table value = %s", value)
338
+	err = proto.Unmarshal(value, &epRec)
339
+	if err != nil {
340
+		logrus.Errorf("Failed to unmarshal service table value: %v", err)
341 341
 		return
342 342
 	}
343 343
 
344
-	name := vals[0]
345
-	svcName := vals[1]
346
-	svcID := vals[2]
347
-	ip := net.ParseIP(vals[3])
344
+	name := epRec.Name
345
+	svcName := epRec.ServiceName
346
+	svcID := epRec.ServiceID
347
+	ip := net.ParseIP(epRec.EndpointIP)
348 348
 
349 349
 	if name == "" || ip == nil {
350 350
 		logrus.Errorf("Invalid endpoint name/ip received while handling service table event %s", value)
351 351
new file mode 100644
... ...
@@ -0,0 +1,501 @@
0
+// Code generated by protoc-gen-gogo.
1
+// source: agent.proto
2
+// DO NOT EDIT!
3
+
4
+/*
5
+	Package libnetwork is a generated protocol buffer package.
6
+
7
+	It is generated from these files:
8
+		agent.proto
9
+
10
+	It has these top-level messages:
11
+		EndpointRecord
12
+*/
13
+package libnetwork
14
+
15
+import proto "github.com/gogo/protobuf/proto"
16
+import fmt "fmt"
17
+import math "math"
18
+import _ "github.com/gogo/protobuf/gogoproto"
19
+
20
+import strings "strings"
21
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
22
+import sort "sort"
23
+import strconv "strconv"
24
+import reflect "reflect"
25
+
26
+import io "io"
27
+
28
+// Reference imports to suppress errors if they are not otherwise used.
29
+var _ = proto.Marshal
30
+var _ = fmt.Errorf
31
+var _ = math.Inf
32
+
33
+// This is a compile-time assertion to ensure that this generated file
34
+// is compatible with the proto package it is being compiled against.
35
+const _ = proto.GoGoProtoPackageIsVersion1
36
+
37
+type EndpointRecord struct {
38
+	Name        string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
39
+	ServiceName string `protobuf:"bytes,2,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"`
40
+	ServiceID   string `protobuf:"bytes,3,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
41
+	EndpointIP  string `protobuf:"bytes,4,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"`
42
+}
43
+
44
+func (m *EndpointRecord) Reset()                    { *m = EndpointRecord{} }
45
+func (*EndpointRecord) ProtoMessage()               {}
46
+func (*EndpointRecord) Descriptor() ([]byte, []int) { return fileDescriptorAgent, []int{0} }
47
+
48
+func init() {
49
+	proto.RegisterType((*EndpointRecord)(nil), "libnetwork.EndpointRecord")
50
+}
51
+func (this *EndpointRecord) GoString() string {
52
+	if this == nil {
53
+		return "nil"
54
+	}
55
+	s := make([]string, 0, 8)
56
+	s = append(s, "&libnetwork.EndpointRecord{")
57
+	s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
58
+	s = append(s, "ServiceName: "+fmt.Sprintf("%#v", this.ServiceName)+",\n")
59
+	s = append(s, "ServiceID: "+fmt.Sprintf("%#v", this.ServiceID)+",\n")
60
+	s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
61
+	s = append(s, "}")
62
+	return strings.Join(s, "")
63
+}
64
+func valueToGoStringAgent(v interface{}, typ string) string {
65
+	rv := reflect.ValueOf(v)
66
+	if rv.IsNil() {
67
+		return "nil"
68
+	}
69
+	pv := reflect.Indirect(rv).Interface()
70
+	return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
71
+}
72
+func extensionToGoStringAgent(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
73
+	if e == nil {
74
+		return "nil"
75
+	}
76
+	s := "map[int32]proto.Extension{"
77
+	keys := make([]int, 0, len(e))
78
+	for k := range e {
79
+		keys = append(keys, int(k))
80
+	}
81
+	sort.Ints(keys)
82
+	ss := []string{}
83
+	for _, k := range keys {
84
+		ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
85
+	}
86
+	s += strings.Join(ss, ",") + "}"
87
+	return s
88
+}
89
+func (m *EndpointRecord) Marshal() (data []byte, err error) {
90
+	size := m.Size()
91
+	data = make([]byte, size)
92
+	n, err := m.MarshalTo(data)
93
+	if err != nil {
94
+		return nil, err
95
+	}
96
+	return data[:n], nil
97
+}
98
+
99
+func (m *EndpointRecord) MarshalTo(data []byte) (int, error) {
100
+	var i int
101
+	_ = i
102
+	var l int
103
+	_ = l
104
+	if len(m.Name) > 0 {
105
+		data[i] = 0xa
106
+		i++
107
+		i = encodeVarintAgent(data, i, uint64(len(m.Name)))
108
+		i += copy(data[i:], m.Name)
109
+	}
110
+	if len(m.ServiceName) > 0 {
111
+		data[i] = 0x12
112
+		i++
113
+		i = encodeVarintAgent(data, i, uint64(len(m.ServiceName)))
114
+		i += copy(data[i:], m.ServiceName)
115
+	}
116
+	if len(m.ServiceID) > 0 {
117
+		data[i] = 0x1a
118
+		i++
119
+		i = encodeVarintAgent(data, i, uint64(len(m.ServiceID)))
120
+		i += copy(data[i:], m.ServiceID)
121
+	}
122
+	if len(m.EndpointIP) > 0 {
123
+		data[i] = 0x22
124
+		i++
125
+		i = encodeVarintAgent(data, i, uint64(len(m.EndpointIP)))
126
+		i += copy(data[i:], m.EndpointIP)
127
+	}
128
+	return i, nil
129
+}
130
+
131
+func encodeFixed64Agent(data []byte, offset int, v uint64) int {
132
+	data[offset] = uint8(v)
133
+	data[offset+1] = uint8(v >> 8)
134
+	data[offset+2] = uint8(v >> 16)
135
+	data[offset+3] = uint8(v >> 24)
136
+	data[offset+4] = uint8(v >> 32)
137
+	data[offset+5] = uint8(v >> 40)
138
+	data[offset+6] = uint8(v >> 48)
139
+	data[offset+7] = uint8(v >> 56)
140
+	return offset + 8
141
+}
142
+func encodeFixed32Agent(data []byte, offset int, v uint32) int {
143
+	data[offset] = uint8(v)
144
+	data[offset+1] = uint8(v >> 8)
145
+	data[offset+2] = uint8(v >> 16)
146
+	data[offset+3] = uint8(v >> 24)
147
+	return offset + 4
148
+}
149
+func encodeVarintAgent(data []byte, offset int, v uint64) int {
150
+	for v >= 1<<7 {
151
+		data[offset] = uint8(v&0x7f | 0x80)
152
+		v >>= 7
153
+		offset++
154
+	}
155
+	data[offset] = uint8(v)
156
+	return offset + 1
157
+}
158
+func (m *EndpointRecord) Size() (n int) {
159
+	var l int
160
+	_ = l
161
+	l = len(m.Name)
162
+	if l > 0 {
163
+		n += 1 + l + sovAgent(uint64(l))
164
+	}
165
+	l = len(m.ServiceName)
166
+	if l > 0 {
167
+		n += 1 + l + sovAgent(uint64(l))
168
+	}
169
+	l = len(m.ServiceID)
170
+	if l > 0 {
171
+		n += 1 + l + sovAgent(uint64(l))
172
+	}
173
+	l = len(m.EndpointIP)
174
+	if l > 0 {
175
+		n += 1 + l + sovAgent(uint64(l))
176
+	}
177
+	return n
178
+}
179
+
180
+func sovAgent(x uint64) (n int) {
181
+	for {
182
+		n++
183
+		x >>= 7
184
+		if x == 0 {
185
+			break
186
+		}
187
+	}
188
+	return n
189
+}
190
+func sozAgent(x uint64) (n int) {
191
+	return sovAgent(uint64((x << 1) ^ uint64((int64(x) >> 63))))
192
+}
193
+func (this *EndpointRecord) String() string {
194
+	if this == nil {
195
+		return "nil"
196
+	}
197
+	s := strings.Join([]string{`&EndpointRecord{`,
198
+		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
199
+		`ServiceName:` + fmt.Sprintf("%v", this.ServiceName) + `,`,
200
+		`ServiceID:` + fmt.Sprintf("%v", this.ServiceID) + `,`,
201
+		`EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
202
+		`}`,
203
+	}, "")
204
+	return s
205
+}
206
+func valueToStringAgent(v interface{}) string {
207
+	rv := reflect.ValueOf(v)
208
+	if rv.IsNil() {
209
+		return "nil"
210
+	}
211
+	pv := reflect.Indirect(rv).Interface()
212
+	return fmt.Sprintf("*%v", pv)
213
+}
214
+func (m *EndpointRecord) Unmarshal(data []byte) error {
215
+	l := len(data)
216
+	iNdEx := 0
217
+	for iNdEx < l {
218
+		preIndex := iNdEx
219
+		var wire uint64
220
+		for shift := uint(0); ; shift += 7 {
221
+			if shift >= 64 {
222
+				return ErrIntOverflowAgent
223
+			}
224
+			if iNdEx >= l {
225
+				return io.ErrUnexpectedEOF
226
+			}
227
+			b := data[iNdEx]
228
+			iNdEx++
229
+			wire |= (uint64(b) & 0x7F) << shift
230
+			if b < 0x80 {
231
+				break
232
+			}
233
+		}
234
+		fieldNum := int32(wire >> 3)
235
+		wireType := int(wire & 0x7)
236
+		if wireType == 4 {
237
+			return fmt.Errorf("proto: EndpointRecord: wiretype end group for non-group")
238
+		}
239
+		if fieldNum <= 0 {
240
+			return fmt.Errorf("proto: EndpointRecord: illegal tag %d (wire type %d)", fieldNum, wire)
241
+		}
242
+		switch fieldNum {
243
+		case 1:
244
+			if wireType != 2 {
245
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
246
+			}
247
+			var stringLen uint64
248
+			for shift := uint(0); ; shift += 7 {
249
+				if shift >= 64 {
250
+					return ErrIntOverflowAgent
251
+				}
252
+				if iNdEx >= l {
253
+					return io.ErrUnexpectedEOF
254
+				}
255
+				b := data[iNdEx]
256
+				iNdEx++
257
+				stringLen |= (uint64(b) & 0x7F) << shift
258
+				if b < 0x80 {
259
+					break
260
+				}
261
+			}
262
+			intStringLen := int(stringLen)
263
+			if intStringLen < 0 {
264
+				return ErrInvalidLengthAgent
265
+			}
266
+			postIndex := iNdEx + intStringLen
267
+			if postIndex > l {
268
+				return io.ErrUnexpectedEOF
269
+			}
270
+			m.Name = string(data[iNdEx:postIndex])
271
+			iNdEx = postIndex
272
+		case 2:
273
+			if wireType != 2 {
274
+				return fmt.Errorf("proto: wrong wireType = %d for field ServiceName", wireType)
275
+			}
276
+			var stringLen uint64
277
+			for shift := uint(0); ; shift += 7 {
278
+				if shift >= 64 {
279
+					return ErrIntOverflowAgent
280
+				}
281
+				if iNdEx >= l {
282
+					return io.ErrUnexpectedEOF
283
+				}
284
+				b := data[iNdEx]
285
+				iNdEx++
286
+				stringLen |= (uint64(b) & 0x7F) << shift
287
+				if b < 0x80 {
288
+					break
289
+				}
290
+			}
291
+			intStringLen := int(stringLen)
292
+			if intStringLen < 0 {
293
+				return ErrInvalidLengthAgent
294
+			}
295
+			postIndex := iNdEx + intStringLen
296
+			if postIndex > l {
297
+				return io.ErrUnexpectedEOF
298
+			}
299
+			m.ServiceName = string(data[iNdEx:postIndex])
300
+			iNdEx = postIndex
301
+		case 3:
302
+			if wireType != 2 {
303
+				return fmt.Errorf("proto: wrong wireType = %d for field ServiceID", wireType)
304
+			}
305
+			var stringLen uint64
306
+			for shift := uint(0); ; shift += 7 {
307
+				if shift >= 64 {
308
+					return ErrIntOverflowAgent
309
+				}
310
+				if iNdEx >= l {
311
+					return io.ErrUnexpectedEOF
312
+				}
313
+				b := data[iNdEx]
314
+				iNdEx++
315
+				stringLen |= (uint64(b) & 0x7F) << shift
316
+				if b < 0x80 {
317
+					break
318
+				}
319
+			}
320
+			intStringLen := int(stringLen)
321
+			if intStringLen < 0 {
322
+				return ErrInvalidLengthAgent
323
+			}
324
+			postIndex := iNdEx + intStringLen
325
+			if postIndex > l {
326
+				return io.ErrUnexpectedEOF
327
+			}
328
+			m.ServiceID = string(data[iNdEx:postIndex])
329
+			iNdEx = postIndex
330
+		case 4:
331
+			if wireType != 2 {
332
+				return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
333
+			}
334
+			var stringLen uint64
335
+			for shift := uint(0); ; shift += 7 {
336
+				if shift >= 64 {
337
+					return ErrIntOverflowAgent
338
+				}
339
+				if iNdEx >= l {
340
+					return io.ErrUnexpectedEOF
341
+				}
342
+				b := data[iNdEx]
343
+				iNdEx++
344
+				stringLen |= (uint64(b) & 0x7F) << shift
345
+				if b < 0x80 {
346
+					break
347
+				}
348
+			}
349
+			intStringLen := int(stringLen)
350
+			if intStringLen < 0 {
351
+				return ErrInvalidLengthAgent
352
+			}
353
+			postIndex := iNdEx + intStringLen
354
+			if postIndex > l {
355
+				return io.ErrUnexpectedEOF
356
+			}
357
+			m.EndpointIP = string(data[iNdEx:postIndex])
358
+			iNdEx = postIndex
359
+		default:
360
+			iNdEx = preIndex
361
+			skippy, err := skipAgent(data[iNdEx:])
362
+			if err != nil {
363
+				return err
364
+			}
365
+			if skippy < 0 {
366
+				return ErrInvalidLengthAgent
367
+			}
368
+			if (iNdEx + skippy) > l {
369
+				return io.ErrUnexpectedEOF
370
+			}
371
+			iNdEx += skippy
372
+		}
373
+	}
374
+
375
+	if iNdEx > l {
376
+		return io.ErrUnexpectedEOF
377
+	}
378
+	return nil
379
+}
380
+func skipAgent(data []byte) (n int, err error) {
381
+	l := len(data)
382
+	iNdEx := 0
383
+	for iNdEx < l {
384
+		var wire uint64
385
+		for shift := uint(0); ; shift += 7 {
386
+			if shift >= 64 {
387
+				return 0, ErrIntOverflowAgent
388
+			}
389
+			if iNdEx >= l {
390
+				return 0, io.ErrUnexpectedEOF
391
+			}
392
+			b := data[iNdEx]
393
+			iNdEx++
394
+			wire |= (uint64(b) & 0x7F) << shift
395
+			if b < 0x80 {
396
+				break
397
+			}
398
+		}
399
+		wireType := int(wire & 0x7)
400
+		switch wireType {
401
+		case 0:
402
+			for shift := uint(0); ; shift += 7 {
403
+				if shift >= 64 {
404
+					return 0, ErrIntOverflowAgent
405
+				}
406
+				if iNdEx >= l {
407
+					return 0, io.ErrUnexpectedEOF
408
+				}
409
+				iNdEx++
410
+				if data[iNdEx-1] < 0x80 {
411
+					break
412
+				}
413
+			}
414
+			return iNdEx, nil
415
+		case 1:
416
+			iNdEx += 8
417
+			return iNdEx, nil
418
+		case 2:
419
+			var length int
420
+			for shift := uint(0); ; shift += 7 {
421
+				if shift >= 64 {
422
+					return 0, ErrIntOverflowAgent
423
+				}
424
+				if iNdEx >= l {
425
+					return 0, io.ErrUnexpectedEOF
426
+				}
427
+				b := data[iNdEx]
428
+				iNdEx++
429
+				length |= (int(b) & 0x7F) << shift
430
+				if b < 0x80 {
431
+					break
432
+				}
433
+			}
434
+			iNdEx += length
435
+			if length < 0 {
436
+				return 0, ErrInvalidLengthAgent
437
+			}
438
+			return iNdEx, nil
439
+		case 3:
440
+			for {
441
+				var innerWire uint64
442
+				var start int = iNdEx
443
+				for shift := uint(0); ; shift += 7 {
444
+					if shift >= 64 {
445
+						return 0, ErrIntOverflowAgent
446
+					}
447
+					if iNdEx >= l {
448
+						return 0, io.ErrUnexpectedEOF
449
+					}
450
+					b := data[iNdEx]
451
+					iNdEx++
452
+					innerWire |= (uint64(b) & 0x7F) << shift
453
+					if b < 0x80 {
454
+						break
455
+					}
456
+				}
457
+				innerWireType := int(innerWire & 0x7)
458
+				if innerWireType == 4 {
459
+					break
460
+				}
461
+				next, err := skipAgent(data[start:])
462
+				if err != nil {
463
+					return 0, err
464
+				}
465
+				iNdEx = start + next
466
+			}
467
+			return iNdEx, nil
468
+		case 4:
469
+			return iNdEx, nil
470
+		case 5:
471
+			iNdEx += 4
472
+			return iNdEx, nil
473
+		default:
474
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
475
+		}
476
+	}
477
+	panic("unreachable")
478
+}
479
+
480
+var (
481
+	ErrInvalidLengthAgent = fmt.Errorf("proto: negative length found during unmarshaling")
482
+	ErrIntOverflowAgent   = fmt.Errorf("proto: integer overflow")
483
+)
484
+
485
+var fileDescriptorAgent = []byte{
486
+	// 204 bytes of a gzipped FileDescriptorProto
487
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x4c, 0x4f, 0xcd,
488
+	0x2b, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xca, 0xc9, 0x4c, 0xca, 0x4b, 0x2d, 0x29,
489
+	0xcf, 0x2f, 0xca, 0x96, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x0b, 0xeb, 0x83, 0x58, 0x10, 0x15,
490
+	0x4a, 0xcb, 0x18, 0xb9, 0xf8, 0x5c, 0xf3, 0x52, 0x0a, 0xf2, 0x33, 0xf3, 0x4a, 0x82, 0x52, 0x93,
491
+	0xf3, 0x8b, 0x52, 0x84, 0x84, 0xb8, 0x58, 0xf2, 0x12, 0x73, 0x53, 0x25, 0x18, 0x15, 0x18, 0x35,
492
+	0x38, 0x83, 0xc0, 0x6c, 0x21, 0x45, 0x2e, 0x9e, 0xe2, 0xd4, 0xa2, 0xb2, 0xcc, 0xe4, 0xd4, 0x78,
493
+	0xb0, 0x1c, 0x13, 0x58, 0x8e, 0x1b, 0x2a, 0xe6, 0x07, 0x52, 0xa2, 0xc3, 0xc5, 0x05, 0x53, 0x92,
494
+	0x99, 0x22, 0xc1, 0x0c, 0x52, 0xe0, 0xc4, 0xfb, 0xe8, 0x9e, 0x3c, 0x67, 0x30, 0x44, 0xd4, 0xd3,
495
+	0x25, 0x88, 0x13, 0xaa, 0xc0, 0x33, 0x45, 0x48, 0x9f, 0x8b, 0x3b, 0x15, 0x6a, 0x6d, 0x7c, 0x66,
496
+	0x81, 0x04, 0x0b, 0x58, 0x39, 0x1f, 0x50, 0x39, 0x17, 0xcc, 0x35, 0x9e, 0x01, 0x41, 0x5c, 0x30,
497
+	0x25, 0x9e, 0x05, 0x4e, 0x12, 0x37, 0x1e, 0xca, 0x31, 0x7c, 0x78, 0x28, 0xc7, 0xd8, 0xf0, 0x48,
498
+	0x8e, 0xf1, 0x04, 0x10, 0x5f, 0x00, 0xe2, 0x07, 0x40, 0x9c, 0xc4, 0x06, 0xf6, 0x89, 0x31, 0x20,
499
+	0x00, 0x00, 0xff, 0xff, 0x94, 0x78, 0x3e, 0xce, 0xfa, 0x00, 0x00, 0x00,
500
+}
0 501
new file mode 100644
... ...
@@ -0,0 +1,19 @@
0
+syntax = "proto3";
1
+
2
+import "gogoproto/gogo.proto";
3
+
4
+package libnetwork;
5
+
6
+option (gogoproto.marshaler_all) = true;
7
+option (gogoproto.unmarshaler_all) = true;
8
+option (gogoproto.stringer_all) = true;
9
+option (gogoproto.gostring_all) = true;
10
+option (gogoproto.sizer_all) = true;
11
+option (gogoproto.goproto_stringer_all) = false;
12
+
13
+message EndpointRecord {
14
+	string name = 1;
15
+	string service_name = 2;
16
+	string service_id = 3 [(gogoproto.customname) = "ServiceID"];
17
+	string endpoint_ip = 4 [(gogoproto.customname) = "EndpointIP"];
18
+}
0 19
\ No newline at end of file