Browse code

Revendor swarmkit to 2eaae1ab6800f8521236e01bafb2667d2ec5371f

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>

Andrea Luzzardi authored on 2016/11/05 04:11:41
Showing 29 changed files
... ...
@@ -100,7 +100,7 @@ github.com/docker/containerd 52ef1ceb4b660c42cf4ea9013180a5663968d4c7
100 100
 github.com/tonistiigi/fifo 8c56881ce5e63e19e2dfc495c8af0fb90916467d
101 101
 
102 102
 # cluster
103
-github.com/docker/swarmkit 4dfc88ccce14ced6f0a6ea82d46dca004c6de0e2
103
+github.com/docker/swarmkit 2eaae1ab6800f8521236e01bafb2667d2ec5371f
104 104
 github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
105 105
 github.com/gogo/protobuf v0.3
106 106
 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"sync"
8 8
 	"time"
9 9
 
10
+	"github.com/docker/swarmkit/agent/exec"
10 11
 	"github.com/docker/swarmkit/api"
11 12
 	"github.com/docker/swarmkit/log"
12 13
 	"golang.org/x/net/context"
... ...
@@ -48,11 +49,8 @@ func New(config *Config) (*Agent, error) {
48 48
 		return nil, err
49 49
 	}
50 50
 
51
-	worker := newWorker(config.DB, config.Executor)
52
-
53 51
 	a := &Agent{
54 52
 		config:   config,
55
-		worker:   worker,
56 53
 		sessionq: make(chan sessionOperation),
57 54
 		started:  make(chan struct{}),
58 55
 		stopped:  make(chan struct{}),
... ...
@@ -60,6 +58,7 @@ func New(config *Config) (*Agent, error) {
60 60
 		ready:    make(chan struct{}),
61 61
 	}
62 62
 
63
+	a.worker = newWorker(config.DB, config.Executor, a)
63 64
 	return a, nil
64 65
 }
65 66
 
... ...
@@ -147,11 +146,12 @@ func (a *Agent) run(ctx context.Context) {
147 147
 	defer nodeUpdateTicker.Stop()
148 148
 
149 149
 	var (
150
-		backoff    time.Duration
151
-		session    = newSession(ctx, a, backoff, "", nodeDescription) // start the initial session
152
-		registered = session.registered
153
-		ready      = a.ready // first session ready
154
-		sessionq   chan sessionOperation
150
+		backoff       time.Duration
151
+		session       = newSession(ctx, a, backoff, "", nodeDescription) // start the initial session
152
+		registered    = session.registered
153
+		ready         = a.ready // first session ready
154
+		sessionq      chan sessionOperation
155
+		subscriptions = map[string]context.CancelFunc{}
155 156
 	)
156 157
 
157 158
 	if err := a.worker.Init(ctx); err != nil {
... ...
@@ -159,6 +159,7 @@ func (a *Agent) run(ctx context.Context) {
159 159
 		a.err = err
160 160
 		return // fatal?
161 161
 	}
162
+	defer a.worker.Close()
162 163
 
163 164
 	// setup a reliable reporter to call back to us.
164 165
 	reporter := newStatusReporter(ctx, a)
... ...
@@ -186,6 +187,23 @@ func (a *Agent) run(ctx context.Context) {
186 186
 			if err := a.handleSessionMessage(ctx, msg); err != nil {
187 187
 				log.G(ctx).WithError(err).Error("session message handler failed")
188 188
 			}
189
+		case sub := <-session.subscriptions:
190
+			if sub.Close {
191
+				if cancel, ok := subscriptions[sub.ID]; ok {
192
+					cancel()
193
+				}
194
+				delete(subscriptions, sub.ID)
195
+				continue
196
+			}
197
+
198
+			if _, ok := subscriptions[sub.ID]; ok {
199
+				// Duplicate subscription
200
+				continue
201
+			}
202
+
203
+			subCtx, subCancel := context.WithCancel(ctx)
204
+			subscriptions[sub.ID] = subCancel
205
+			go a.worker.Subscribe(subCtx, sub)
189 206
 		case <-registered:
190 207
 			log.G(ctx).Debugln("agent: registered")
191 208
 			if ready != nil {
... ...
@@ -387,6 +405,40 @@ func (a *Agent) UpdateTaskStatus(ctx context.Context, taskID string, status *api
387 387
 	}
388 388
 }
389 389
 
390
+// Publisher returns a LogPublisher for the given subscription
391
+func (a *Agent) Publisher(ctx context.Context, subscriptionID string) (exec.LogPublisher, error) {
392
+	// TODO(stevvooe): The level of coordination here is WAY too much for logs.
393
+	// These should only be best effort and really just buffer until a session is
394
+	// ready. Ideally, they would use a separate connection completely.
395
+
396
+	var (
397
+		err    error
398
+		client api.LogBroker_PublishLogsClient
399
+	)
400
+
401
+	err = a.withSession(ctx, func(session *session) error {
402
+		client, err = api.NewLogBrokerClient(session.conn).PublishLogs(ctx)
403
+		return err
404
+	})
405
+	if err != nil {
406
+		return nil, err
407
+	}
408
+
409
+	return exec.LogPublisherFunc(func(ctx context.Context, message api.LogMessage) error {
410
+		select {
411
+		case <-ctx.Done():
412
+			client.CloseSend()
413
+			return ctx.Err()
414
+		default:
415
+		}
416
+
417
+		return client.Send(&api.PublishLogsMessage{
418
+			SubscriptionID: subscriptionID,
419
+			Messages:       []api.LogMessage{message},
420
+		})
421
+	}), nil
422
+}
423
+
390 424
 // nodeDescriptionWithHostname retrieves node description, and overrides hostname if available
391 425
 func (a *Agent) nodeDescriptionWithHostname(ctx context.Context) (*api.NodeDescription, error) {
392 426
 	desc, err := a.config.Executor.Describe(ctx)
... ...
@@ -45,6 +45,33 @@ type Controller interface {
45 45
 	Close() error
46 46
 }
47 47
 
48
+// ControllerLogs defines a component that makes logs accessible.
49
+//
50
+// Can usually be accessed on a controller instance via type assertion.
51
+type ControllerLogs interface {
52
+	// Logs will write publisher until the context is cancelled or an error
53
+	// occurs.
54
+	Logs(ctx context.Context, publisher LogPublisher, options api.LogSubscriptionOptions) error
55
+}
56
+
57
+// LogPublisher defines the protocol for receiving a log message.
58
+type LogPublisher interface {
59
+	Publish(ctx context.Context, message api.LogMessage) error
60
+}
61
+
62
+// LogPublisherFunc implements publisher with just a function.
63
+type LogPublisherFunc func(ctx context.Context, message api.LogMessage) error
64
+
65
+// Publish calls the wrapped function.
66
+func (fn LogPublisherFunc) Publish(ctx context.Context, message api.LogMessage) error {
67
+	return fn(ctx, message)
68
+}
69
+
70
+// LogPublisherProvider defines the protocol for receiving a log publisher
71
+type LogPublisherProvider interface {
72
+	Publisher(ctx context.Context, subscriptionID string) (LogPublisher, error)
73
+}
74
+
48 75
 // ContainerStatuser reports status of a container.
49 76
 //
50 77
 // This can be implemented by controllers or error types.
... ...
@@ -110,6 +110,100 @@ func (_mr *_MockControllerRecorder) Close() *gomock.Call {
110 110
 	return _mr.mock.ctrl.RecordCall(_mr.mock, "Close")
111 111
 }
112 112
 
113
+// Mock of ControllerLogs interface
114
+type MockControllerLogs struct {
115
+	ctrl     *gomock.Controller
116
+	recorder *_MockControllerLogsRecorder
117
+}
118
+
119
+// Recorder for MockControllerLogs (not exported)
120
+type _MockControllerLogsRecorder struct {
121
+	mock *MockControllerLogs
122
+}
123
+
124
+func NewMockControllerLogs(ctrl *gomock.Controller) *MockControllerLogs {
125
+	mock := &MockControllerLogs{ctrl: ctrl}
126
+	mock.recorder = &_MockControllerLogsRecorder{mock}
127
+	return mock
128
+}
129
+
130
+func (_m *MockControllerLogs) EXPECT() *_MockControllerLogsRecorder {
131
+	return _m.recorder
132
+}
133
+
134
+func (_m *MockControllerLogs) Logs(ctx context.Context, publisher LogPublisher, options api.LogSubscriptionOptions) error {
135
+	ret := _m.ctrl.Call(_m, "Logs", ctx, publisher, options)
136
+	ret0, _ := ret[0].(error)
137
+	return ret0
138
+}
139
+
140
+func (_mr *_MockControllerLogsRecorder) Logs(arg0, arg1, arg2 interface{}) *gomock.Call {
141
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Logs", arg0, arg1, arg2)
142
+}
143
+
144
+// Mock of LogPublisher interface
145
+type MockLogPublisher struct {
146
+	ctrl     *gomock.Controller
147
+	recorder *_MockLogPublisherRecorder
148
+}
149
+
150
+// Recorder for MockLogPublisher (not exported)
151
+type _MockLogPublisherRecorder struct {
152
+	mock *MockLogPublisher
153
+}
154
+
155
+func NewMockLogPublisher(ctrl *gomock.Controller) *MockLogPublisher {
156
+	mock := &MockLogPublisher{ctrl: ctrl}
157
+	mock.recorder = &_MockLogPublisherRecorder{mock}
158
+	return mock
159
+}
160
+
161
+func (_m *MockLogPublisher) EXPECT() *_MockLogPublisherRecorder {
162
+	return _m.recorder
163
+}
164
+
165
+func (_m *MockLogPublisher) Publish(ctx context.Context, message api.LogMessage) error {
166
+	ret := _m.ctrl.Call(_m, "Publish", ctx, message)
167
+	ret0, _ := ret[0].(error)
168
+	return ret0
169
+}
170
+
171
+func (_mr *_MockLogPublisherRecorder) Publish(arg0, arg1 interface{}) *gomock.Call {
172
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Publish", arg0, arg1)
173
+}
174
+
175
+// Mock of LogPublisherProvider interface
176
+type MockLogPublisherProvider struct {
177
+	ctrl     *gomock.Controller
178
+	recorder *_MockLogPublisherProviderRecorder
179
+}
180
+
181
+// Recorder for MockLogPublisherProvider (not exported)
182
+type _MockLogPublisherProviderRecorder struct {
183
+	mock *MockLogPublisherProvider
184
+}
185
+
186
+func NewMockLogPublisherProvider(ctrl *gomock.Controller) *MockLogPublisherProvider {
187
+	mock := &MockLogPublisherProvider{ctrl: ctrl}
188
+	mock.recorder = &_MockLogPublisherProviderRecorder{mock}
189
+	return mock
190
+}
191
+
192
+func (_m *MockLogPublisherProvider) EXPECT() *_MockLogPublisherProviderRecorder {
193
+	return _m.recorder
194
+}
195
+
196
+func (_m *MockLogPublisherProvider) Publisher(ctx context.Context, subscriptionID string) (LogPublisher, error) {
197
+	ret := _m.ctrl.Call(_m, "Publisher", ctx, subscriptionID)
198
+	ret0, _ := ret[0].(LogPublisher)
199
+	ret1, _ := ret[1].(error)
200
+	return ret0, ret1
201
+}
202
+
203
+func (_mr *_MockLogPublisherProviderRecorder) Publisher(arg0, arg1 interface{}) *gomock.Call {
204
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Publisher", arg0, arg1)
205
+}
206
+
113 207
 // Mock of ContainerStatuser interface
114 208
 type MockContainerStatuser struct {
115 209
 	ctrl     *gomock.Controller
... ...
@@ -33,12 +33,13 @@ type session struct {
33 33
 	conn *grpc.ClientConn
34 34
 	addr string
35 35
 
36
-	agent       *Agent
37
-	sessionID   string
38
-	session     api.Dispatcher_SessionClient
39
-	errs        chan error
40
-	messages    chan *api.SessionMessage
41
-	assignments chan *api.AssignmentsMessage
36
+	agent         *Agent
37
+	sessionID     string
38
+	session       api.Dispatcher_SessionClient
39
+	errs          chan error
40
+	messages      chan *api.SessionMessage
41
+	assignments   chan *api.AssignmentsMessage
42
+	subscriptions chan *api.SubscriptionMessage
42 43
 
43 44
 	registered chan struct{} // closed registration
44 45
 	closed     chan struct{}
... ...
@@ -47,14 +48,19 @@ type session struct {
47 47
 
48 48
 func newSession(ctx context.Context, agent *Agent, delay time.Duration, sessionID string, description *api.NodeDescription) *session {
49 49
 	s := &session{
50
-		agent:       agent,
51
-		sessionID:   sessionID,
52
-		errs:        make(chan error, 1),
53
-		messages:    make(chan *api.SessionMessage),
54
-		assignments: make(chan *api.AssignmentsMessage),
55
-		registered:  make(chan struct{}),
56
-		closed:      make(chan struct{}),
50
+		agent:         agent,
51
+		sessionID:     sessionID,
52
+		errs:          make(chan error, 1),
53
+		messages:      make(chan *api.SessionMessage),
54
+		assignments:   make(chan *api.AssignmentsMessage),
55
+		subscriptions: make(chan *api.SubscriptionMessage),
56
+		registered:    make(chan struct{}),
57
+		closed:        make(chan struct{}),
57 58
 	}
59
+
60
+	// TODO(stevvooe): Need to move connection management up a level or create
61
+	// independent connection for log broker client.
62
+
58 63
 	peer, err := agent.config.Managers.Select()
59 64
 	if err != nil {
60 65
 		s.errs <- err
... ...
@@ -98,6 +104,7 @@ func (s *session) run(ctx context.Context, delay time.Duration, description *api
98 98
 	go runctx(ctx, s.closed, s.errs, s.heartbeat)
99 99
 	go runctx(ctx, s.closed, s.errs, s.watch)
100 100
 	go runctx(ctx, s.closed, s.errs, s.listen)
101
+	go runctx(ctx, s.closed, s.errs, s.logSubscriptions)
101 102
 
102 103
 	close(s.registered)
103 104
 }
... ...
@@ -213,6 +220,33 @@ func (s *session) handleSessionMessage(ctx context.Context, msg *api.SessionMess
213 213
 	}
214 214
 }
215 215
 
216
+func (s *session) logSubscriptions(ctx context.Context) error {
217
+	log := log.G(ctx).WithFields(logrus.Fields{"method": "(*session).logSubscriptions"})
218
+	log.Debugf("")
219
+
220
+	client := api.NewLogBrokerClient(s.conn)
221
+	subscriptions, err := client.ListenSubscriptions(ctx, &api.ListenSubscriptionsRequest{})
222
+	if err != nil {
223
+		return err
224
+	}
225
+	defer subscriptions.CloseSend()
226
+
227
+	for {
228
+		resp, err := subscriptions.Recv()
229
+		if err != nil {
230
+			return err
231
+		}
232
+
233
+		select {
234
+		case s.subscriptions <- resp:
235
+		case <-s.closed:
236
+			return errSessionClosed
237
+		case <-ctx.Done():
238
+			return ctx.Err()
239
+		}
240
+	}
241
+}
242
+
216 243
 func (s *session) watch(ctx context.Context) error {
217 244
 	log := log.G(ctx).WithFields(logrus.Fields{"method": "(*session).watch"})
218 245
 	log.Debugf("")
... ...
@@ -64,6 +64,18 @@ func (tm *taskManager) Close() error {
64 64
 	}
65 65
 }
66 66
 
67
+func (tm *taskManager) Logs(ctx context.Context, options api.LogSubscriptionOptions, publisher exec.LogPublisher) {
68
+	ctx = log.WithModule(ctx, "taskmanager")
69
+
70
+	logCtlr, ok := tm.ctlr.(exec.ControllerLogs)
71
+	if !ok {
72
+		return // no logs available
73
+	}
74
+	if err := logCtlr.Logs(ctx, publisher, options); err != nil {
75
+		log.G(ctx).WithError(err).Errorf("logs call failed")
76
+	}
77
+}
78
+
67 79
 func (tm *taskManager) run(ctx context.Context) {
68 80
 	ctx, cancelAll := context.WithCancel(ctx)
69 81
 	defer cancelAll() // cancel all child operations on exit.
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"github.com/docker/swarmkit/agent/exec"
9 9
 	"github.com/docker/swarmkit/api"
10 10
 	"github.com/docker/swarmkit/log"
11
+	"github.com/docker/swarmkit/watch"
11 12
 	"golang.org/x/net/context"
12 13
 )
13 14
 
... ...
@@ -17,6 +18,11 @@ type Worker interface {
17 17
 	// Init prepares the worker for task assignment.
18 18
 	Init(ctx context.Context) error
19 19
 
20
+	// Close performs worker cleanup when no longer needed.
21
+	//
22
+	// It is not safe to call any worker function after that.
23
+	Close()
24
+
20 25
 	// Assign assigns a complete set of tasks and secrets to a worker. Any task or secrets not included in
21 26
 	// this set will be removed.
22 27
 	Assign(ctx context.Context, assignments []*api.AssignmentChange) error
... ...
@@ -31,6 +37,9 @@ type Worker interface {
31 31
 	//
32 32
 	// The listener will be removed if the context is cancelled.
33 33
 	Listen(ctx context.Context, reporter StatusReporter)
34
+
35
+	// Subscribe to log messages matching the subscription.
36
+	Subscribe(ctx context.Context, subscription *api.SubscriptionMessage) error
34 37
 }
35 38
 
36 39
 // statusReporterKey protects removal map from panic.
... ...
@@ -39,20 +48,25 @@ type statusReporterKey struct {
39 39
 }
40 40
 
41 41
 type worker struct {
42
-	db        *bolt.DB
43
-	executor  exec.Executor
44
-	listeners map[*statusReporterKey]struct{}
42
+	db                *bolt.DB
43
+	executor          exec.Executor
44
+	publisher         exec.LogPublisher
45
+	listeners         map[*statusReporterKey]struct{}
46
+	taskevents        *watch.Queue
47
+	publisherProvider exec.LogPublisherProvider
45 48
 
46 49
 	taskManagers map[string]*taskManager
47 50
 	mu           sync.RWMutex
48 51
 }
49 52
 
50
-func newWorker(db *bolt.DB, executor exec.Executor) *worker {
53
+func newWorker(db *bolt.DB, executor exec.Executor, publisherProvider exec.LogPublisherProvider) *worker {
51 54
 	return &worker{
52
-		db:           db,
53
-		executor:     executor,
54
-		listeners:    make(map[*statusReporterKey]struct{}),
55
-		taskManagers: make(map[string]*taskManager),
55
+		db:                db,
56
+		executor:          executor,
57
+		publisherProvider: publisherProvider,
58
+		taskevents:        watch.NewQueue(),
59
+		listeners:         make(map[*statusReporterKey]struct{}),
60
+		taskManagers:      make(map[string]*taskManager),
56 61
 	}
57 62
 }
58 63
 
... ...
@@ -90,6 +104,11 @@ func (w *worker) Init(ctx context.Context) error {
90 90
 	})
91 91
 }
92 92
 
93
+// Close performs worker cleanup when no longer needed.
94
+func (w *worker) Close() {
95
+	w.taskevents.Close()
96
+}
97
+
93 98
 // Assign assigns a full set of tasks and secrets to the worker.
94 99
 // Any tasks not previously known will be started. Any tasks that are in the task set
95 100
 // and already running will be updated, if possible. Any tasks currently running on
... ...
@@ -319,6 +338,7 @@ func (w *worker) Listen(ctx context.Context, reporter StatusReporter) {
319 319
 }
320 320
 
321 321
 func (w *worker) startTask(ctx context.Context, tx *bolt.Tx, task *api.Task) error {
322
+	w.taskevents.Publish(task.Copy())
322 323
 	_, err := w.taskManager(ctx, tx, task) // side-effect taskManager creation.
323 324
 
324 325
 	if err != nil {
... ...
@@ -381,3 +401,63 @@ func (w *worker) updateTaskStatus(ctx context.Context, tx *bolt.Tx, taskID strin
381 381
 
382 382
 	return nil
383 383
 }
384
+
385
+// Subscribe to log messages matching the subscription.
386
+func (w *worker) Subscribe(ctx context.Context, subscription *api.SubscriptionMessage) error {
387
+	log.G(ctx).Debugf("Received subscription %s (selector: %v)", subscription.ID, subscription.Selector)
388
+
389
+	publisher, err := w.publisherProvider.Publisher(ctx, subscription.ID)
390
+	if err != nil {
391
+		return err
392
+	}
393
+	// Send a close once we're done
394
+	defer publisher.Publish(ctx, api.LogMessage{})
395
+
396
+	match := func(t *api.Task) bool {
397
+		// TODO(aluzzardi): Consider using maps to limit the iterations.
398
+		for _, tid := range subscription.Selector.TaskIDs {
399
+			if t.ID == tid {
400
+				return true
401
+			}
402
+		}
403
+
404
+		for _, sid := range subscription.Selector.ServiceIDs {
405
+			if t.ServiceID == sid {
406
+				return true
407
+			}
408
+		}
409
+
410
+		for _, nid := range subscription.Selector.NodeIDs {
411
+			if t.NodeID == nid {
412
+				return true
413
+			}
414
+		}
415
+
416
+		return false
417
+	}
418
+
419
+	ch, cancel := w.taskevents.Watch()
420
+	defer cancel()
421
+
422
+	w.mu.Lock()
423
+	for _, tm := range w.taskManagers {
424
+		if match(tm.task) {
425
+			go tm.Logs(ctx, *subscription.Options, publisher)
426
+		}
427
+	}
428
+	w.mu.Unlock()
429
+
430
+	for {
431
+		select {
432
+		case v := <-ch:
433
+			w.mu.Lock()
434
+			task := v.(*api.Task)
435
+			if match(task) {
436
+				go w.taskManagers[task.ID].Logs(ctx, *subscription.Options, publisher)
437
+			}
438
+			w.mu.Unlock()
439
+		case <-ctx.Done():
440
+			return ctx.Err()
441
+		}
442
+	}
443
+}
... ...
@@ -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,Mtimestamp/timestamp.proto=github.com/docker/swarmkit/api/timestamp,Mduration/duration.proto=github.com/docker/swarmkit/api/duration,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto
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,Mtimestamp/timestamp.proto=github.com/docker/swarmkit/api/timestamp,Mduration/duration.proto=github.com/docker/swarmkit/api/duration,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto logbroker.proto
4 4
new file mode 100644
... ...
@@ -0,0 +1,3130 @@
0
+// Code generated by protoc-gen-gogo.
1
+// source: logbroker.proto
2
+// DO NOT EDIT!
3
+
4
+package api
5
+
6
+import proto "github.com/gogo/protobuf/proto"
7
+import fmt "fmt"
8
+import math "math"
9
+import _ "github.com/gogo/protobuf/gogoproto"
10
+import docker_swarmkit_v1 "github.com/docker/swarmkit/api/timestamp"
11
+import _ "github.com/docker/swarmkit/protobuf/plugin"
12
+
13
+import strings "strings"
14
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
15
+import sort "sort"
16
+import strconv "strconv"
17
+import reflect "reflect"
18
+
19
+import (
20
+	context "golang.org/x/net/context"
21
+	grpc "google.golang.org/grpc"
22
+)
23
+
24
+import raftselector "github.com/docker/swarmkit/manager/raftselector"
25
+import codes "google.golang.org/grpc/codes"
26
+import metadata "google.golang.org/grpc/metadata"
27
+import transport "google.golang.org/grpc/transport"
28
+import time "time"
29
+
30
+import io "io"
31
+
32
+// Reference imports to suppress errors if they are not otherwise used.
33
+var _ = proto.Marshal
34
+var _ = fmt.Errorf
35
+var _ = math.Inf
36
+
37
+// LogStream defines the stream from which the log message came.
38
+type LogStream int32
39
+
40
+const (
41
+	LogStreamUnknown LogStream = 0
42
+	LogStreamStdout  LogStream = 1
43
+	LogStreamStderr  LogStream = 2
44
+)
45
+
46
+var LogStream_name = map[int32]string{
47
+	0: "LOG_STREAM_UNKNOWN",
48
+	1: "LOG_STREAM_STDOUT",
49
+	2: "LOG_STREAM_STDERR",
50
+}
51
+var LogStream_value = map[string]int32{
52
+	"LOG_STREAM_UNKNOWN": 0,
53
+	"LOG_STREAM_STDOUT":  1,
54
+	"LOG_STREAM_STDERR":  2,
55
+}
56
+
57
+func (x LogStream) String() string {
58
+	return proto.EnumName(LogStream_name, int32(x))
59
+}
60
+func (LogStream) EnumDescriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{0} }
61
+
62
+type LogSubscriptionOptions struct {
63
+	// Streams defines which log streams should be sent from the task source.
64
+	// Empty means send all the messages.
65
+	Streams []LogStream `protobuf:"varint,1,rep,name=streams,enum=docker.swarmkit.v1.LogStream" json:"streams,omitempty"`
66
+	// Follow instructs the publisher to continue sending log messages as they
67
+	// are produced, after satisfying the initial query.
68
+	Follow bool `protobuf:"varint,2,opt,name=follow,proto3" json:"follow,omitempty"`
69
+	// Tail defines how many messages relative to the log stream to send when
70
+	// starting the stream.
71
+	//
72
+	// Positive values will skip that number of messages from the start of the
73
+	// stream before publishing.
74
+	//
75
+	// Negative values will specify messages relative to the end of the stream,
76
+	// offset by one. We can say that the last (-n-1) lines are returned when n
77
+	// < 0. As reference, -1 would mean send no log lines (typically used with
78
+	// follow), -2 would return the last log line, -11 would return the last 10
79
+	// and so on.
80
+	//
81
+	// The default value of zero will return all logs.
82
+	//
83
+	// Note that this is very different from the Docker API.
84
+	Tail int64 `protobuf:"varint,3,opt,name=tail,proto3" json:"tail,omitempty"`
85
+	// Since indicates that only log messages produced after this timestamp
86
+	// should be sent.
87
+	Since *docker_swarmkit_v1.Timestamp `protobuf:"bytes,4,opt,name=since" json:"since,omitempty"`
88
+}
89
+
90
+func (m *LogSubscriptionOptions) Reset()                    { *m = LogSubscriptionOptions{} }
91
+func (*LogSubscriptionOptions) ProtoMessage()               {}
92
+func (*LogSubscriptionOptions) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{0} }
93
+
94
+// LogSelector will match logs from ANY of the defined parameters.
95
+//
96
+// For the best effect, the client should use the least specific parameter
97
+// possible. For example, if they want to listen to all the tasks of a service,
98
+// they should use the service id, rather than specifying the individual tasks.
99
+type LogSelector struct {
100
+	ServiceIDs []string `protobuf:"bytes,1,rep,name=service_ids,json=serviceIds" json:"service_ids,omitempty"`
101
+	NodeIDs    []string `protobuf:"bytes,2,rep,name=node_ids,json=nodeIds" json:"node_ids,omitempty"`
102
+	TaskIDs    []string `protobuf:"bytes,3,rep,name=task_ids,json=taskIds" json:"task_ids,omitempty"`
103
+}
104
+
105
+func (m *LogSelector) Reset()                    { *m = LogSelector{} }
106
+func (*LogSelector) ProtoMessage()               {}
107
+func (*LogSelector) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{1} }
108
+
109
+// LogContext marks the context from which a log message was generated.
110
+type LogContext struct {
111
+	ServiceID string `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
112
+	NodeID    string `protobuf:"bytes,2,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
113
+	TaskID    string `protobuf:"bytes,3,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"`
114
+}
115
+
116
+func (m *LogContext) Reset()                    { *m = LogContext{} }
117
+func (*LogContext) ProtoMessage()               {}
118
+func (*LogContext) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{2} }
119
+
120
+// LogMessage
121
+type LogMessage struct {
122
+	// Context identifies the source of the log message.
123
+	Context LogContext `protobuf:"bytes,1,opt,name=context" json:"context"`
124
+	// Timestamp is the time at which the message was generated.
125
+	Timestamp *docker_swarmkit_v1.Timestamp `protobuf:"bytes,2,opt,name=timestamp" json:"timestamp,omitempty"`
126
+	// Stream identifies the stream of the log message, stdout or stderr.
127
+	Stream LogStream `protobuf:"varint,3,opt,name=stream,proto3,enum=docker.swarmkit.v1.LogStream" json:"stream,omitempty"`
128
+	// Data is the raw log message, as generated by the application.
129
+	Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
130
+}
131
+
132
+func (m *LogMessage) Reset()                    { *m = LogMessage{} }
133
+func (*LogMessage) ProtoMessage()               {}
134
+func (*LogMessage) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{3} }
135
+
136
+type SubscribeLogsRequest struct {
137
+	// LogSelector describes the logs to which the subscriber is
138
+	Selector *LogSelector            `protobuf:"bytes,1,opt,name=selector" json:"selector,omitempty"`
139
+	Options  *LogSubscriptionOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"`
140
+}
141
+
142
+func (m *SubscribeLogsRequest) Reset()                    { *m = SubscribeLogsRequest{} }
143
+func (*SubscribeLogsRequest) ProtoMessage()               {}
144
+func (*SubscribeLogsRequest) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{4} }
145
+
146
+type SubscribeLogsMessage struct {
147
+	Messages []LogMessage `protobuf:"bytes,1,rep,name=messages" json:"messages"`
148
+}
149
+
150
+func (m *SubscribeLogsMessage) Reset()                    { *m = SubscribeLogsMessage{} }
151
+func (*SubscribeLogsMessage) ProtoMessage()               {}
152
+func (*SubscribeLogsMessage) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{5} }
153
+
154
+// ListenSubscriptionsRequest is a placeholder to begin listening for
155
+// subscriptions.
156
+type ListenSubscriptionsRequest struct {
157
+}
158
+
159
+func (m *ListenSubscriptionsRequest) Reset()      { *m = ListenSubscriptionsRequest{} }
160
+func (*ListenSubscriptionsRequest) ProtoMessage() {}
161
+func (*ListenSubscriptionsRequest) Descriptor() ([]byte, []int) {
162
+	return fileDescriptorLogbroker, []int{6}
163
+}
164
+
165
+// SubscriptionMessage instructs the listener to start publishing messages for
166
+// the stream or end a subscription.
167
+//
168
+// If Options.Follow == false, the worker should end the subscription on its own.
169
+type SubscriptionMessage struct {
170
+	// ID identifies the subscription.
171
+	ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
172
+	// Selector defines which sources should be sent for the subscription.
173
+	Selector *LogSelector `protobuf:"bytes,2,opt,name=selector" json:"selector,omitempty"`
174
+	// Options specify how the subscription should be satisfied.
175
+	Options *LogSubscriptionOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
176
+	// Close will be true if the node should shutdown the subscription with the
177
+	// provided identifier.
178
+	Close bool `protobuf:"varint,4,opt,name=close,proto3" json:"close,omitempty"`
179
+}
180
+
181
+func (m *SubscriptionMessage) Reset()                    { *m = SubscriptionMessage{} }
182
+func (*SubscriptionMessage) ProtoMessage()               {}
183
+func (*SubscriptionMessage) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{7} }
184
+
185
+type PublishLogsMessage struct {
186
+	// SubscriptionID identifies which subscription the set of messages should
187
+	// be sent to. We can think of this as a "mail box" for the subscription.
188
+	SubscriptionID string `protobuf:"bytes,1,opt,name=subscription_id,json=subscriptionId,proto3" json:"subscription_id,omitempty"`
189
+	// Messages is the log message for publishing.
190
+	Messages []LogMessage `protobuf:"bytes,2,rep,name=messages" json:"messages"`
191
+}
192
+
193
+func (m *PublishLogsMessage) Reset()                    { *m = PublishLogsMessage{} }
194
+func (*PublishLogsMessage) ProtoMessage()               {}
195
+func (*PublishLogsMessage) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{8} }
196
+
197
+type PublishLogsResponse struct {
198
+}
199
+
200
+func (m *PublishLogsResponse) Reset()                    { *m = PublishLogsResponse{} }
201
+func (*PublishLogsResponse) ProtoMessage()               {}
202
+func (*PublishLogsResponse) Descriptor() ([]byte, []int) { return fileDescriptorLogbroker, []int{9} }
203
+
204
+func init() {
205
+	proto.RegisterType((*LogSubscriptionOptions)(nil), "docker.swarmkit.v1.LogSubscriptionOptions")
206
+	proto.RegisterType((*LogSelector)(nil), "docker.swarmkit.v1.LogSelector")
207
+	proto.RegisterType((*LogContext)(nil), "docker.swarmkit.v1.LogContext")
208
+	proto.RegisterType((*LogMessage)(nil), "docker.swarmkit.v1.LogMessage")
209
+	proto.RegisterType((*SubscribeLogsRequest)(nil), "docker.swarmkit.v1.SubscribeLogsRequest")
210
+	proto.RegisterType((*SubscribeLogsMessage)(nil), "docker.swarmkit.v1.SubscribeLogsMessage")
211
+	proto.RegisterType((*ListenSubscriptionsRequest)(nil), "docker.swarmkit.v1.ListenSubscriptionsRequest")
212
+	proto.RegisterType((*SubscriptionMessage)(nil), "docker.swarmkit.v1.SubscriptionMessage")
213
+	proto.RegisterType((*PublishLogsMessage)(nil), "docker.swarmkit.v1.PublishLogsMessage")
214
+	proto.RegisterType((*PublishLogsResponse)(nil), "docker.swarmkit.v1.PublishLogsResponse")
215
+	proto.RegisterEnum("docker.swarmkit.v1.LogStream", LogStream_name, LogStream_value)
216
+}
217
+
218
+type authenticatedWrapperLogsServer struct {
219
+	local     LogsServer
220
+	authorize func(context.Context, []string) error
221
+}
222
+
223
+func NewAuthenticatedWrapperLogsServer(local LogsServer, authorize func(context.Context, []string) error) LogsServer {
224
+	return &authenticatedWrapperLogsServer{
225
+		local:     local,
226
+		authorize: authorize,
227
+	}
228
+}
229
+
230
+func (p *authenticatedWrapperLogsServer) SubscribeLogs(r *SubscribeLogsRequest, stream Logs_SubscribeLogsServer) error {
231
+
232
+	if err := p.authorize(stream.Context(), []string{"swarm-manager"}); err != nil {
233
+		return err
234
+	}
235
+	return p.local.SubscribeLogs(r, stream)
236
+}
237
+
238
+type authenticatedWrapperLogBrokerServer struct {
239
+	local     LogBrokerServer
240
+	authorize func(context.Context, []string) error
241
+}
242
+
243
+func NewAuthenticatedWrapperLogBrokerServer(local LogBrokerServer, authorize func(context.Context, []string) error) LogBrokerServer {
244
+	return &authenticatedWrapperLogBrokerServer{
245
+		local:     local,
246
+		authorize: authorize,
247
+	}
248
+}
249
+
250
+func (p *authenticatedWrapperLogBrokerServer) ListenSubscriptions(r *ListenSubscriptionsRequest, stream LogBroker_ListenSubscriptionsServer) error {
251
+
252
+	if err := p.authorize(stream.Context(), []string{"swarm-worker", "swarm-manager"}); err != nil {
253
+		return err
254
+	}
255
+	return p.local.ListenSubscriptions(r, stream)
256
+}
257
+
258
+func (p *authenticatedWrapperLogBrokerServer) PublishLogs(stream LogBroker_PublishLogsServer) error {
259
+
260
+	if err := p.authorize(stream.Context(), []string{"swarm-worker", "swarm-manager"}); err != nil {
261
+		return err
262
+	}
263
+	return p.local.PublishLogs(stream)
264
+}
265
+
266
+func (m *LogSubscriptionOptions) Copy() *LogSubscriptionOptions {
267
+	if m == nil {
268
+		return nil
269
+	}
270
+
271
+	o := &LogSubscriptionOptions{
272
+		Follow: m.Follow,
273
+		Tail:   m.Tail,
274
+		Since:  m.Since.Copy(),
275
+	}
276
+
277
+	if m.Streams != nil {
278
+		o.Streams = make([]LogStream, 0, len(m.Streams))
279
+		o.Streams = append(o.Streams, m.Streams...)
280
+	}
281
+
282
+	return o
283
+}
284
+
285
+func (m *LogSelector) Copy() *LogSelector {
286
+	if m == nil {
287
+		return nil
288
+	}
289
+
290
+	o := &LogSelector{}
291
+
292
+	if m.ServiceIDs != nil {
293
+		o.ServiceIDs = make([]string, 0, len(m.ServiceIDs))
294
+		o.ServiceIDs = append(o.ServiceIDs, m.ServiceIDs...)
295
+	}
296
+
297
+	if m.NodeIDs != nil {
298
+		o.NodeIDs = make([]string, 0, len(m.NodeIDs))
299
+		o.NodeIDs = append(o.NodeIDs, m.NodeIDs...)
300
+	}
301
+
302
+	if m.TaskIDs != nil {
303
+		o.TaskIDs = make([]string, 0, len(m.TaskIDs))
304
+		o.TaskIDs = append(o.TaskIDs, m.TaskIDs...)
305
+	}
306
+
307
+	return o
308
+}
309
+
310
+func (m *LogContext) Copy() *LogContext {
311
+	if m == nil {
312
+		return nil
313
+	}
314
+
315
+	o := &LogContext{
316
+		ServiceID: m.ServiceID,
317
+		NodeID:    m.NodeID,
318
+		TaskID:    m.TaskID,
319
+	}
320
+
321
+	return o
322
+}
323
+
324
+func (m *LogMessage) Copy() *LogMessage {
325
+	if m == nil {
326
+		return nil
327
+	}
328
+
329
+	o := &LogMessage{
330
+		Context:   *m.Context.Copy(),
331
+		Timestamp: m.Timestamp.Copy(),
332
+		Stream:    m.Stream,
333
+		Data:      m.Data,
334
+	}
335
+
336
+	return o
337
+}
338
+
339
+func (m *SubscribeLogsRequest) Copy() *SubscribeLogsRequest {
340
+	if m == nil {
341
+		return nil
342
+	}
343
+
344
+	o := &SubscribeLogsRequest{
345
+		Selector: m.Selector.Copy(),
346
+		Options:  m.Options.Copy(),
347
+	}
348
+
349
+	return o
350
+}
351
+
352
+func (m *SubscribeLogsMessage) Copy() *SubscribeLogsMessage {
353
+	if m == nil {
354
+		return nil
355
+	}
356
+
357
+	o := &SubscribeLogsMessage{}
358
+
359
+	if m.Messages != nil {
360
+		o.Messages = make([]LogMessage, 0, len(m.Messages))
361
+		for _, v := range m.Messages {
362
+			o.Messages = append(o.Messages, *v.Copy())
363
+		}
364
+	}
365
+
366
+	return o
367
+}
368
+
369
+func (m *ListenSubscriptionsRequest) Copy() *ListenSubscriptionsRequest {
370
+	if m == nil {
371
+		return nil
372
+	}
373
+
374
+	o := &ListenSubscriptionsRequest{}
375
+
376
+	return o
377
+}
378
+
379
+func (m *SubscriptionMessage) Copy() *SubscriptionMessage {
380
+	if m == nil {
381
+		return nil
382
+	}
383
+
384
+	o := &SubscriptionMessage{
385
+		ID:       m.ID,
386
+		Selector: m.Selector.Copy(),
387
+		Options:  m.Options.Copy(),
388
+		Close:    m.Close,
389
+	}
390
+
391
+	return o
392
+}
393
+
394
+func (m *PublishLogsMessage) Copy() *PublishLogsMessage {
395
+	if m == nil {
396
+		return nil
397
+	}
398
+
399
+	o := &PublishLogsMessage{
400
+		SubscriptionID: m.SubscriptionID,
401
+	}
402
+
403
+	if m.Messages != nil {
404
+		o.Messages = make([]LogMessage, 0, len(m.Messages))
405
+		for _, v := range m.Messages {
406
+			o.Messages = append(o.Messages, *v.Copy())
407
+		}
408
+	}
409
+
410
+	return o
411
+}
412
+
413
+func (m *PublishLogsResponse) Copy() *PublishLogsResponse {
414
+	if m == nil {
415
+		return nil
416
+	}
417
+
418
+	o := &PublishLogsResponse{}
419
+
420
+	return o
421
+}
422
+
423
+func (this *LogSubscriptionOptions) GoString() string {
424
+	if this == nil {
425
+		return "nil"
426
+	}
427
+	s := make([]string, 0, 8)
428
+	s = append(s, "&api.LogSubscriptionOptions{")
429
+	s = append(s, "Streams: "+fmt.Sprintf("%#v", this.Streams)+",\n")
430
+	s = append(s, "Follow: "+fmt.Sprintf("%#v", this.Follow)+",\n")
431
+	s = append(s, "Tail: "+fmt.Sprintf("%#v", this.Tail)+",\n")
432
+	if this.Since != nil {
433
+		s = append(s, "Since: "+fmt.Sprintf("%#v", this.Since)+",\n")
434
+	}
435
+	s = append(s, "}")
436
+	return strings.Join(s, "")
437
+}
438
+func (this *LogSelector) GoString() string {
439
+	if this == nil {
440
+		return "nil"
441
+	}
442
+	s := make([]string, 0, 7)
443
+	s = append(s, "&api.LogSelector{")
444
+	s = append(s, "ServiceIDs: "+fmt.Sprintf("%#v", this.ServiceIDs)+",\n")
445
+	s = append(s, "NodeIDs: "+fmt.Sprintf("%#v", this.NodeIDs)+",\n")
446
+	s = append(s, "TaskIDs: "+fmt.Sprintf("%#v", this.TaskIDs)+",\n")
447
+	s = append(s, "}")
448
+	return strings.Join(s, "")
449
+}
450
+func (this *LogContext) GoString() string {
451
+	if this == nil {
452
+		return "nil"
453
+	}
454
+	s := make([]string, 0, 7)
455
+	s = append(s, "&api.LogContext{")
456
+	s = append(s, "ServiceID: "+fmt.Sprintf("%#v", this.ServiceID)+",\n")
457
+	s = append(s, "NodeID: "+fmt.Sprintf("%#v", this.NodeID)+",\n")
458
+	s = append(s, "TaskID: "+fmt.Sprintf("%#v", this.TaskID)+",\n")
459
+	s = append(s, "}")
460
+	return strings.Join(s, "")
461
+}
462
+func (this *LogMessage) GoString() string {
463
+	if this == nil {
464
+		return "nil"
465
+	}
466
+	s := make([]string, 0, 8)
467
+	s = append(s, "&api.LogMessage{")
468
+	s = append(s, "Context: "+strings.Replace(this.Context.GoString(), `&`, ``, 1)+",\n")
469
+	if this.Timestamp != nil {
470
+		s = append(s, "Timestamp: "+fmt.Sprintf("%#v", this.Timestamp)+",\n")
471
+	}
472
+	s = append(s, "Stream: "+fmt.Sprintf("%#v", this.Stream)+",\n")
473
+	s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n")
474
+	s = append(s, "}")
475
+	return strings.Join(s, "")
476
+}
477
+func (this *SubscribeLogsRequest) GoString() string {
478
+	if this == nil {
479
+		return "nil"
480
+	}
481
+	s := make([]string, 0, 6)
482
+	s = append(s, "&api.SubscribeLogsRequest{")
483
+	if this.Selector != nil {
484
+		s = append(s, "Selector: "+fmt.Sprintf("%#v", this.Selector)+",\n")
485
+	}
486
+	if this.Options != nil {
487
+		s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
488
+	}
489
+	s = append(s, "}")
490
+	return strings.Join(s, "")
491
+}
492
+func (this *SubscribeLogsMessage) GoString() string {
493
+	if this == nil {
494
+		return "nil"
495
+	}
496
+	s := make([]string, 0, 5)
497
+	s = append(s, "&api.SubscribeLogsMessage{")
498
+	if this.Messages != nil {
499
+		s = append(s, "Messages: "+fmt.Sprintf("%#v", this.Messages)+",\n")
500
+	}
501
+	s = append(s, "}")
502
+	return strings.Join(s, "")
503
+}
504
+func (this *ListenSubscriptionsRequest) GoString() string {
505
+	if this == nil {
506
+		return "nil"
507
+	}
508
+	s := make([]string, 0, 4)
509
+	s = append(s, "&api.ListenSubscriptionsRequest{")
510
+	s = append(s, "}")
511
+	return strings.Join(s, "")
512
+}
513
+func (this *SubscriptionMessage) GoString() string {
514
+	if this == nil {
515
+		return "nil"
516
+	}
517
+	s := make([]string, 0, 8)
518
+	s = append(s, "&api.SubscriptionMessage{")
519
+	s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n")
520
+	if this.Selector != nil {
521
+		s = append(s, "Selector: "+fmt.Sprintf("%#v", this.Selector)+",\n")
522
+	}
523
+	if this.Options != nil {
524
+		s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
525
+	}
526
+	s = append(s, "Close: "+fmt.Sprintf("%#v", this.Close)+",\n")
527
+	s = append(s, "}")
528
+	return strings.Join(s, "")
529
+}
530
+func (this *PublishLogsMessage) GoString() string {
531
+	if this == nil {
532
+		return "nil"
533
+	}
534
+	s := make([]string, 0, 6)
535
+	s = append(s, "&api.PublishLogsMessage{")
536
+	s = append(s, "SubscriptionID: "+fmt.Sprintf("%#v", this.SubscriptionID)+",\n")
537
+	if this.Messages != nil {
538
+		s = append(s, "Messages: "+fmt.Sprintf("%#v", this.Messages)+",\n")
539
+	}
540
+	s = append(s, "}")
541
+	return strings.Join(s, "")
542
+}
543
+func (this *PublishLogsResponse) GoString() string {
544
+	if this == nil {
545
+		return "nil"
546
+	}
547
+	s := make([]string, 0, 4)
548
+	s = append(s, "&api.PublishLogsResponse{")
549
+	s = append(s, "}")
550
+	return strings.Join(s, "")
551
+}
552
+func valueToGoStringLogbroker(v interface{}, typ string) string {
553
+	rv := reflect.ValueOf(v)
554
+	if rv.IsNil() {
555
+		return "nil"
556
+	}
557
+	pv := reflect.Indirect(rv).Interface()
558
+	return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
559
+}
560
+func extensionToGoStringLogbroker(m github_com_gogo_protobuf_proto.Message) string {
561
+	e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m)
562
+	if e == nil {
563
+		return "nil"
564
+	}
565
+	s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"
566
+	keys := make([]int, 0, len(e))
567
+	for k := range e {
568
+		keys = append(keys, int(k))
569
+	}
570
+	sort.Ints(keys)
571
+	ss := []string{}
572
+	for _, k := range keys {
573
+		ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
574
+	}
575
+	s += strings.Join(ss, ",") + "})"
576
+	return s
577
+}
578
+
579
+// Reference imports to suppress errors if they are not otherwise used.
580
+var _ context.Context
581
+var _ grpc.ClientConn
582
+
583
+// This is a compile-time assertion to ensure that this generated file
584
+// is compatible with the grpc package it is being compiled against.
585
+const _ = grpc.SupportPackageIsVersion3
586
+
587
+// Client API for Logs service
588
+
589
+type LogsClient interface {
590
+	// SubscribeLogs starts a subscription with the specified selector and options.
591
+	//
592
+	// The subscription will be distributed to relevant nodes and messages will
593
+	// be collected and sent via the returned stream.
594
+	//
595
+	// The subscription will end with an EOF.
596
+	SubscribeLogs(ctx context.Context, in *SubscribeLogsRequest, opts ...grpc.CallOption) (Logs_SubscribeLogsClient, error)
597
+}
598
+
599
+type logsClient struct {
600
+	cc *grpc.ClientConn
601
+}
602
+
603
+func NewLogsClient(cc *grpc.ClientConn) LogsClient {
604
+	return &logsClient{cc}
605
+}
606
+
607
+func (c *logsClient) SubscribeLogs(ctx context.Context, in *SubscribeLogsRequest, opts ...grpc.CallOption) (Logs_SubscribeLogsClient, error) {
608
+	stream, err := grpc.NewClientStream(ctx, &_Logs_serviceDesc.Streams[0], c.cc, "/docker.swarmkit.v1.Logs/SubscribeLogs", opts...)
609
+	if err != nil {
610
+		return nil, err
611
+	}
612
+	x := &logsSubscribeLogsClient{stream}
613
+	if err := x.ClientStream.SendMsg(in); err != nil {
614
+		return nil, err
615
+	}
616
+	if err := x.ClientStream.CloseSend(); err != nil {
617
+		return nil, err
618
+	}
619
+	return x, nil
620
+}
621
+
622
+type Logs_SubscribeLogsClient interface {
623
+	Recv() (*SubscribeLogsMessage, error)
624
+	grpc.ClientStream
625
+}
626
+
627
+type logsSubscribeLogsClient struct {
628
+	grpc.ClientStream
629
+}
630
+
631
+func (x *logsSubscribeLogsClient) Recv() (*SubscribeLogsMessage, error) {
632
+	m := new(SubscribeLogsMessage)
633
+	if err := x.ClientStream.RecvMsg(m); err != nil {
634
+		return nil, err
635
+	}
636
+	return m, nil
637
+}
638
+
639
+// Server API for Logs service
640
+
641
+type LogsServer interface {
642
+	// SubscribeLogs starts a subscription with the specified selector and options.
643
+	//
644
+	// The subscription will be distributed to relevant nodes and messages will
645
+	// be collected and sent via the returned stream.
646
+	//
647
+	// The subscription will end with an EOF.
648
+	SubscribeLogs(*SubscribeLogsRequest, Logs_SubscribeLogsServer) error
649
+}
650
+
651
+func RegisterLogsServer(s *grpc.Server, srv LogsServer) {
652
+	s.RegisterService(&_Logs_serviceDesc, srv)
653
+}
654
+
655
+func _Logs_SubscribeLogs_Handler(srv interface{}, stream grpc.ServerStream) error {
656
+	m := new(SubscribeLogsRequest)
657
+	if err := stream.RecvMsg(m); err != nil {
658
+		return err
659
+	}
660
+	return srv.(LogsServer).SubscribeLogs(m, &logsSubscribeLogsServer{stream})
661
+}
662
+
663
+type Logs_SubscribeLogsServer interface {
664
+	Send(*SubscribeLogsMessage) error
665
+	grpc.ServerStream
666
+}
667
+
668
+type logsSubscribeLogsServer struct {
669
+	grpc.ServerStream
670
+}
671
+
672
+func (x *logsSubscribeLogsServer) Send(m *SubscribeLogsMessage) error {
673
+	return x.ServerStream.SendMsg(m)
674
+}
675
+
676
+var _Logs_serviceDesc = grpc.ServiceDesc{
677
+	ServiceName: "docker.swarmkit.v1.Logs",
678
+	HandlerType: (*LogsServer)(nil),
679
+	Methods:     []grpc.MethodDesc{},
680
+	Streams: []grpc.StreamDesc{
681
+		{
682
+			StreamName:    "SubscribeLogs",
683
+			Handler:       _Logs_SubscribeLogs_Handler,
684
+			ServerStreams: true,
685
+		},
686
+	},
687
+	Metadata: fileDescriptorLogbroker,
688
+}
689
+
690
+// Client API for LogBroker service
691
+
692
+type LogBrokerClient interface {
693
+	// ListenSubscriptions starts a subscription stream for the node. For each
694
+	// message received, the node should attempt to satisfy the subscription.
695
+	//
696
+	// Log messages that match the provided subscription should be sent via
697
+	// PublishLogs.
698
+	ListenSubscriptions(ctx context.Context, in *ListenSubscriptionsRequest, opts ...grpc.CallOption) (LogBroker_ListenSubscriptionsClient, error)
699
+	// PublishLogs receives sets of log messages destined for a single
700
+	// subscription identifier.
701
+	PublishLogs(ctx context.Context, opts ...grpc.CallOption) (LogBroker_PublishLogsClient, error)
702
+}
703
+
704
+type logBrokerClient struct {
705
+	cc *grpc.ClientConn
706
+}
707
+
708
+func NewLogBrokerClient(cc *grpc.ClientConn) LogBrokerClient {
709
+	return &logBrokerClient{cc}
710
+}
711
+
712
+func (c *logBrokerClient) ListenSubscriptions(ctx context.Context, in *ListenSubscriptionsRequest, opts ...grpc.CallOption) (LogBroker_ListenSubscriptionsClient, error) {
713
+	stream, err := grpc.NewClientStream(ctx, &_LogBroker_serviceDesc.Streams[0], c.cc, "/docker.swarmkit.v1.LogBroker/ListenSubscriptions", opts...)
714
+	if err != nil {
715
+		return nil, err
716
+	}
717
+	x := &logBrokerListenSubscriptionsClient{stream}
718
+	if err := x.ClientStream.SendMsg(in); err != nil {
719
+		return nil, err
720
+	}
721
+	if err := x.ClientStream.CloseSend(); err != nil {
722
+		return nil, err
723
+	}
724
+	return x, nil
725
+}
726
+
727
+type LogBroker_ListenSubscriptionsClient interface {
728
+	Recv() (*SubscriptionMessage, error)
729
+	grpc.ClientStream
730
+}
731
+
732
+type logBrokerListenSubscriptionsClient struct {
733
+	grpc.ClientStream
734
+}
735
+
736
+func (x *logBrokerListenSubscriptionsClient) Recv() (*SubscriptionMessage, error) {
737
+	m := new(SubscriptionMessage)
738
+	if err := x.ClientStream.RecvMsg(m); err != nil {
739
+		return nil, err
740
+	}
741
+	return m, nil
742
+}
743
+
744
+func (c *logBrokerClient) PublishLogs(ctx context.Context, opts ...grpc.CallOption) (LogBroker_PublishLogsClient, error) {
745
+	stream, err := grpc.NewClientStream(ctx, &_LogBroker_serviceDesc.Streams[1], c.cc, "/docker.swarmkit.v1.LogBroker/PublishLogs", opts...)
746
+	if err != nil {
747
+		return nil, err
748
+	}
749
+	x := &logBrokerPublishLogsClient{stream}
750
+	return x, nil
751
+}
752
+
753
+type LogBroker_PublishLogsClient interface {
754
+	Send(*PublishLogsMessage) error
755
+	CloseAndRecv() (*PublishLogsResponse, error)
756
+	grpc.ClientStream
757
+}
758
+
759
+type logBrokerPublishLogsClient struct {
760
+	grpc.ClientStream
761
+}
762
+
763
+func (x *logBrokerPublishLogsClient) Send(m *PublishLogsMessage) error {
764
+	return x.ClientStream.SendMsg(m)
765
+}
766
+
767
+func (x *logBrokerPublishLogsClient) CloseAndRecv() (*PublishLogsResponse, error) {
768
+	if err := x.ClientStream.CloseSend(); err != nil {
769
+		return nil, err
770
+	}
771
+	m := new(PublishLogsResponse)
772
+	if err := x.ClientStream.RecvMsg(m); err != nil {
773
+		return nil, err
774
+	}
775
+	return m, nil
776
+}
777
+
778
+// Server API for LogBroker service
779
+
780
+type LogBrokerServer interface {
781
+	// ListenSubscriptions starts a subscription stream for the node. For each
782
+	// message received, the node should attempt to satisfy the subscription.
783
+	//
784
+	// Log messages that match the provided subscription should be sent via
785
+	// PublishLogs.
786
+	ListenSubscriptions(*ListenSubscriptionsRequest, LogBroker_ListenSubscriptionsServer) error
787
+	// PublishLogs receives sets of log messages destined for a single
788
+	// subscription identifier.
789
+	PublishLogs(LogBroker_PublishLogsServer) error
790
+}
791
+
792
+func RegisterLogBrokerServer(s *grpc.Server, srv LogBrokerServer) {
793
+	s.RegisterService(&_LogBroker_serviceDesc, srv)
794
+}
795
+
796
+func _LogBroker_ListenSubscriptions_Handler(srv interface{}, stream grpc.ServerStream) error {
797
+	m := new(ListenSubscriptionsRequest)
798
+	if err := stream.RecvMsg(m); err != nil {
799
+		return err
800
+	}
801
+	return srv.(LogBrokerServer).ListenSubscriptions(m, &logBrokerListenSubscriptionsServer{stream})
802
+}
803
+
804
+type LogBroker_ListenSubscriptionsServer interface {
805
+	Send(*SubscriptionMessage) error
806
+	grpc.ServerStream
807
+}
808
+
809
+type logBrokerListenSubscriptionsServer struct {
810
+	grpc.ServerStream
811
+}
812
+
813
+func (x *logBrokerListenSubscriptionsServer) Send(m *SubscriptionMessage) error {
814
+	return x.ServerStream.SendMsg(m)
815
+}
816
+
817
+func _LogBroker_PublishLogs_Handler(srv interface{}, stream grpc.ServerStream) error {
818
+	return srv.(LogBrokerServer).PublishLogs(&logBrokerPublishLogsServer{stream})
819
+}
820
+
821
+type LogBroker_PublishLogsServer interface {
822
+	SendAndClose(*PublishLogsResponse) error
823
+	Recv() (*PublishLogsMessage, error)
824
+	grpc.ServerStream
825
+}
826
+
827
+type logBrokerPublishLogsServer struct {
828
+	grpc.ServerStream
829
+}
830
+
831
+func (x *logBrokerPublishLogsServer) SendAndClose(m *PublishLogsResponse) error {
832
+	return x.ServerStream.SendMsg(m)
833
+}
834
+
835
+func (x *logBrokerPublishLogsServer) Recv() (*PublishLogsMessage, error) {
836
+	m := new(PublishLogsMessage)
837
+	if err := x.ServerStream.RecvMsg(m); err != nil {
838
+		return nil, err
839
+	}
840
+	return m, nil
841
+}
842
+
843
+var _LogBroker_serviceDesc = grpc.ServiceDesc{
844
+	ServiceName: "docker.swarmkit.v1.LogBroker",
845
+	HandlerType: (*LogBrokerServer)(nil),
846
+	Methods:     []grpc.MethodDesc{},
847
+	Streams: []grpc.StreamDesc{
848
+		{
849
+			StreamName:    "ListenSubscriptions",
850
+			Handler:       _LogBroker_ListenSubscriptions_Handler,
851
+			ServerStreams: true,
852
+		},
853
+		{
854
+			StreamName:    "PublishLogs",
855
+			Handler:       _LogBroker_PublishLogs_Handler,
856
+			ClientStreams: true,
857
+		},
858
+	},
859
+	Metadata: fileDescriptorLogbroker,
860
+}
861
+
862
+func (m *LogSubscriptionOptions) Marshal() (data []byte, err error) {
863
+	size := m.Size()
864
+	data = make([]byte, size)
865
+	n, err := m.MarshalTo(data)
866
+	if err != nil {
867
+		return nil, err
868
+	}
869
+	return data[:n], nil
870
+}
871
+
872
+func (m *LogSubscriptionOptions) MarshalTo(data []byte) (int, error) {
873
+	var i int
874
+	_ = i
875
+	var l int
876
+	_ = l
877
+	if len(m.Streams) > 0 {
878
+		for _, num := range m.Streams {
879
+			data[i] = 0x8
880
+			i++
881
+			i = encodeVarintLogbroker(data, i, uint64(num))
882
+		}
883
+	}
884
+	if m.Follow {
885
+		data[i] = 0x10
886
+		i++
887
+		if m.Follow {
888
+			data[i] = 1
889
+		} else {
890
+			data[i] = 0
891
+		}
892
+		i++
893
+	}
894
+	if m.Tail != 0 {
895
+		data[i] = 0x18
896
+		i++
897
+		i = encodeVarintLogbroker(data, i, uint64(m.Tail))
898
+	}
899
+	if m.Since != nil {
900
+		data[i] = 0x22
901
+		i++
902
+		i = encodeVarintLogbroker(data, i, uint64(m.Since.Size()))
903
+		n1, err := m.Since.MarshalTo(data[i:])
904
+		if err != nil {
905
+			return 0, err
906
+		}
907
+		i += n1
908
+	}
909
+	return i, nil
910
+}
911
+
912
+func (m *LogSelector) Marshal() (data []byte, err error) {
913
+	size := m.Size()
914
+	data = make([]byte, size)
915
+	n, err := m.MarshalTo(data)
916
+	if err != nil {
917
+		return nil, err
918
+	}
919
+	return data[:n], nil
920
+}
921
+
922
+func (m *LogSelector) MarshalTo(data []byte) (int, error) {
923
+	var i int
924
+	_ = i
925
+	var l int
926
+	_ = l
927
+	if len(m.ServiceIDs) > 0 {
928
+		for _, s := range m.ServiceIDs {
929
+			data[i] = 0xa
930
+			i++
931
+			l = len(s)
932
+			for l >= 1<<7 {
933
+				data[i] = uint8(uint64(l)&0x7f | 0x80)
934
+				l >>= 7
935
+				i++
936
+			}
937
+			data[i] = uint8(l)
938
+			i++
939
+			i += copy(data[i:], s)
940
+		}
941
+	}
942
+	if len(m.NodeIDs) > 0 {
943
+		for _, s := range m.NodeIDs {
944
+			data[i] = 0x12
945
+			i++
946
+			l = len(s)
947
+			for l >= 1<<7 {
948
+				data[i] = uint8(uint64(l)&0x7f | 0x80)
949
+				l >>= 7
950
+				i++
951
+			}
952
+			data[i] = uint8(l)
953
+			i++
954
+			i += copy(data[i:], s)
955
+		}
956
+	}
957
+	if len(m.TaskIDs) > 0 {
958
+		for _, s := range m.TaskIDs {
959
+			data[i] = 0x1a
960
+			i++
961
+			l = len(s)
962
+			for l >= 1<<7 {
963
+				data[i] = uint8(uint64(l)&0x7f | 0x80)
964
+				l >>= 7
965
+				i++
966
+			}
967
+			data[i] = uint8(l)
968
+			i++
969
+			i += copy(data[i:], s)
970
+		}
971
+	}
972
+	return i, nil
973
+}
974
+
975
+func (m *LogContext) Marshal() (data []byte, err error) {
976
+	size := m.Size()
977
+	data = make([]byte, size)
978
+	n, err := m.MarshalTo(data)
979
+	if err != nil {
980
+		return nil, err
981
+	}
982
+	return data[:n], nil
983
+}
984
+
985
+func (m *LogContext) MarshalTo(data []byte) (int, error) {
986
+	var i int
987
+	_ = i
988
+	var l int
989
+	_ = l
990
+	if len(m.ServiceID) > 0 {
991
+		data[i] = 0xa
992
+		i++
993
+		i = encodeVarintLogbroker(data, i, uint64(len(m.ServiceID)))
994
+		i += copy(data[i:], m.ServiceID)
995
+	}
996
+	if len(m.NodeID) > 0 {
997
+		data[i] = 0x12
998
+		i++
999
+		i = encodeVarintLogbroker(data, i, uint64(len(m.NodeID)))
1000
+		i += copy(data[i:], m.NodeID)
1001
+	}
1002
+	if len(m.TaskID) > 0 {
1003
+		data[i] = 0x1a
1004
+		i++
1005
+		i = encodeVarintLogbroker(data, i, uint64(len(m.TaskID)))
1006
+		i += copy(data[i:], m.TaskID)
1007
+	}
1008
+	return i, nil
1009
+}
1010
+
1011
+func (m *LogMessage) Marshal() (data []byte, err error) {
1012
+	size := m.Size()
1013
+	data = make([]byte, size)
1014
+	n, err := m.MarshalTo(data)
1015
+	if err != nil {
1016
+		return nil, err
1017
+	}
1018
+	return data[:n], nil
1019
+}
1020
+
1021
+func (m *LogMessage) MarshalTo(data []byte) (int, error) {
1022
+	var i int
1023
+	_ = i
1024
+	var l int
1025
+	_ = l
1026
+	data[i] = 0xa
1027
+	i++
1028
+	i = encodeVarintLogbroker(data, i, uint64(m.Context.Size()))
1029
+	n2, err := m.Context.MarshalTo(data[i:])
1030
+	if err != nil {
1031
+		return 0, err
1032
+	}
1033
+	i += n2
1034
+	if m.Timestamp != nil {
1035
+		data[i] = 0x12
1036
+		i++
1037
+		i = encodeVarintLogbroker(data, i, uint64(m.Timestamp.Size()))
1038
+		n3, err := m.Timestamp.MarshalTo(data[i:])
1039
+		if err != nil {
1040
+			return 0, err
1041
+		}
1042
+		i += n3
1043
+	}
1044
+	if m.Stream != 0 {
1045
+		data[i] = 0x18
1046
+		i++
1047
+		i = encodeVarintLogbroker(data, i, uint64(m.Stream))
1048
+	}
1049
+	if len(m.Data) > 0 {
1050
+		data[i] = 0x22
1051
+		i++
1052
+		i = encodeVarintLogbroker(data, i, uint64(len(m.Data)))
1053
+		i += copy(data[i:], m.Data)
1054
+	}
1055
+	return i, nil
1056
+}
1057
+
1058
+func (m *SubscribeLogsRequest) Marshal() (data []byte, err error) {
1059
+	size := m.Size()
1060
+	data = make([]byte, size)
1061
+	n, err := m.MarshalTo(data)
1062
+	if err != nil {
1063
+		return nil, err
1064
+	}
1065
+	return data[:n], nil
1066
+}
1067
+
1068
+func (m *SubscribeLogsRequest) MarshalTo(data []byte) (int, error) {
1069
+	var i int
1070
+	_ = i
1071
+	var l int
1072
+	_ = l
1073
+	if m.Selector != nil {
1074
+		data[i] = 0xa
1075
+		i++
1076
+		i = encodeVarintLogbroker(data, i, uint64(m.Selector.Size()))
1077
+		n4, err := m.Selector.MarshalTo(data[i:])
1078
+		if err != nil {
1079
+			return 0, err
1080
+		}
1081
+		i += n4
1082
+	}
1083
+	if m.Options != nil {
1084
+		data[i] = 0x12
1085
+		i++
1086
+		i = encodeVarintLogbroker(data, i, uint64(m.Options.Size()))
1087
+		n5, err := m.Options.MarshalTo(data[i:])
1088
+		if err != nil {
1089
+			return 0, err
1090
+		}
1091
+		i += n5
1092
+	}
1093
+	return i, nil
1094
+}
1095
+
1096
+func (m *SubscribeLogsMessage) Marshal() (data []byte, err error) {
1097
+	size := m.Size()
1098
+	data = make([]byte, size)
1099
+	n, err := m.MarshalTo(data)
1100
+	if err != nil {
1101
+		return nil, err
1102
+	}
1103
+	return data[:n], nil
1104
+}
1105
+
1106
+func (m *SubscribeLogsMessage) MarshalTo(data []byte) (int, error) {
1107
+	var i int
1108
+	_ = i
1109
+	var l int
1110
+	_ = l
1111
+	if len(m.Messages) > 0 {
1112
+		for _, msg := range m.Messages {
1113
+			data[i] = 0xa
1114
+			i++
1115
+			i = encodeVarintLogbroker(data, i, uint64(msg.Size()))
1116
+			n, err := msg.MarshalTo(data[i:])
1117
+			if err != nil {
1118
+				return 0, err
1119
+			}
1120
+			i += n
1121
+		}
1122
+	}
1123
+	return i, nil
1124
+}
1125
+
1126
+func (m *ListenSubscriptionsRequest) Marshal() (data []byte, err error) {
1127
+	size := m.Size()
1128
+	data = make([]byte, size)
1129
+	n, err := m.MarshalTo(data)
1130
+	if err != nil {
1131
+		return nil, err
1132
+	}
1133
+	return data[:n], nil
1134
+}
1135
+
1136
+func (m *ListenSubscriptionsRequest) MarshalTo(data []byte) (int, error) {
1137
+	var i int
1138
+	_ = i
1139
+	var l int
1140
+	_ = l
1141
+	return i, nil
1142
+}
1143
+
1144
+func (m *SubscriptionMessage) Marshal() (data []byte, err error) {
1145
+	size := m.Size()
1146
+	data = make([]byte, size)
1147
+	n, err := m.MarshalTo(data)
1148
+	if err != nil {
1149
+		return nil, err
1150
+	}
1151
+	return data[:n], nil
1152
+}
1153
+
1154
+func (m *SubscriptionMessage) MarshalTo(data []byte) (int, error) {
1155
+	var i int
1156
+	_ = i
1157
+	var l int
1158
+	_ = l
1159
+	if len(m.ID) > 0 {
1160
+		data[i] = 0xa
1161
+		i++
1162
+		i = encodeVarintLogbroker(data, i, uint64(len(m.ID)))
1163
+		i += copy(data[i:], m.ID)
1164
+	}
1165
+	if m.Selector != nil {
1166
+		data[i] = 0x12
1167
+		i++
1168
+		i = encodeVarintLogbroker(data, i, uint64(m.Selector.Size()))
1169
+		n6, err := m.Selector.MarshalTo(data[i:])
1170
+		if err != nil {
1171
+			return 0, err
1172
+		}
1173
+		i += n6
1174
+	}
1175
+	if m.Options != nil {
1176
+		data[i] = 0x1a
1177
+		i++
1178
+		i = encodeVarintLogbroker(data, i, uint64(m.Options.Size()))
1179
+		n7, err := m.Options.MarshalTo(data[i:])
1180
+		if err != nil {
1181
+			return 0, err
1182
+		}
1183
+		i += n7
1184
+	}
1185
+	if m.Close {
1186
+		data[i] = 0x20
1187
+		i++
1188
+		if m.Close {
1189
+			data[i] = 1
1190
+		} else {
1191
+			data[i] = 0
1192
+		}
1193
+		i++
1194
+	}
1195
+	return i, nil
1196
+}
1197
+
1198
+func (m *PublishLogsMessage) Marshal() (data []byte, err error) {
1199
+	size := m.Size()
1200
+	data = make([]byte, size)
1201
+	n, err := m.MarshalTo(data)
1202
+	if err != nil {
1203
+		return nil, err
1204
+	}
1205
+	return data[:n], nil
1206
+}
1207
+
1208
+func (m *PublishLogsMessage) MarshalTo(data []byte) (int, error) {
1209
+	var i int
1210
+	_ = i
1211
+	var l int
1212
+	_ = l
1213
+	if len(m.SubscriptionID) > 0 {
1214
+		data[i] = 0xa
1215
+		i++
1216
+		i = encodeVarintLogbroker(data, i, uint64(len(m.SubscriptionID)))
1217
+		i += copy(data[i:], m.SubscriptionID)
1218
+	}
1219
+	if len(m.Messages) > 0 {
1220
+		for _, msg := range m.Messages {
1221
+			data[i] = 0x12
1222
+			i++
1223
+			i = encodeVarintLogbroker(data, i, uint64(msg.Size()))
1224
+			n, err := msg.MarshalTo(data[i:])
1225
+			if err != nil {
1226
+				return 0, err
1227
+			}
1228
+			i += n
1229
+		}
1230
+	}
1231
+	return i, nil
1232
+}
1233
+
1234
+func (m *PublishLogsResponse) Marshal() (data []byte, err error) {
1235
+	size := m.Size()
1236
+	data = make([]byte, size)
1237
+	n, err := m.MarshalTo(data)
1238
+	if err != nil {
1239
+		return nil, err
1240
+	}
1241
+	return data[:n], nil
1242
+}
1243
+
1244
+func (m *PublishLogsResponse) MarshalTo(data []byte) (int, error) {
1245
+	var i int
1246
+	_ = i
1247
+	var l int
1248
+	_ = l
1249
+	return i, nil
1250
+}
1251
+
1252
+func encodeFixed64Logbroker(data []byte, offset int, v uint64) int {
1253
+	data[offset] = uint8(v)
1254
+	data[offset+1] = uint8(v >> 8)
1255
+	data[offset+2] = uint8(v >> 16)
1256
+	data[offset+3] = uint8(v >> 24)
1257
+	data[offset+4] = uint8(v >> 32)
1258
+	data[offset+5] = uint8(v >> 40)
1259
+	data[offset+6] = uint8(v >> 48)
1260
+	data[offset+7] = uint8(v >> 56)
1261
+	return offset + 8
1262
+}
1263
+func encodeFixed32Logbroker(data []byte, offset int, v uint32) int {
1264
+	data[offset] = uint8(v)
1265
+	data[offset+1] = uint8(v >> 8)
1266
+	data[offset+2] = uint8(v >> 16)
1267
+	data[offset+3] = uint8(v >> 24)
1268
+	return offset + 4
1269
+}
1270
+func encodeVarintLogbroker(data []byte, offset int, v uint64) int {
1271
+	for v >= 1<<7 {
1272
+		data[offset] = uint8(v&0x7f | 0x80)
1273
+		v >>= 7
1274
+		offset++
1275
+	}
1276
+	data[offset] = uint8(v)
1277
+	return offset + 1
1278
+}
1279
+
1280
+type raftProxyLogsServer struct {
1281
+	local        LogsServer
1282
+	connSelector raftselector.ConnProvider
1283
+	ctxMods      []func(context.Context) (context.Context, error)
1284
+}
1285
+
1286
+func NewRaftProxyLogsServer(local LogsServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) LogsServer {
1287
+	redirectChecker := func(ctx context.Context) (context.Context, error) {
1288
+		s, ok := transport.StreamFromContext(ctx)
1289
+		if !ok {
1290
+			return ctx, grpc.Errorf(codes.InvalidArgument, "remote addr is not found in context")
1291
+		}
1292
+		addr := s.ServerTransport().RemoteAddr().String()
1293
+		md, ok := metadata.FromContext(ctx)
1294
+		if ok && len(md["redirect"]) != 0 {
1295
+			return ctx, grpc.Errorf(codes.ResourceExhausted, "more than one redirect to leader from: %s", md["redirect"])
1296
+		}
1297
+		if !ok {
1298
+			md = metadata.New(map[string]string{})
1299
+		}
1300
+		md["redirect"] = append(md["redirect"], addr)
1301
+		return metadata.NewContext(ctx, md), nil
1302
+	}
1303
+	mods := []func(context.Context) (context.Context, error){redirectChecker}
1304
+	mods = append(mods, ctxMod)
1305
+
1306
+	return &raftProxyLogsServer{
1307
+		local:        local,
1308
+		connSelector: connSelector,
1309
+		ctxMods:      mods,
1310
+	}
1311
+}
1312
+func (p *raftProxyLogsServer) runCtxMods(ctx context.Context) (context.Context, error) {
1313
+	var err error
1314
+	for _, mod := range p.ctxMods {
1315
+		ctx, err = mod(ctx)
1316
+		if err != nil {
1317
+			return ctx, err
1318
+		}
1319
+	}
1320
+	return ctx, nil
1321
+}
1322
+func (p *raftProxyLogsServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) {
1323
+	ticker := time.NewTicker(500 * time.Millisecond)
1324
+	defer ticker.Stop()
1325
+	for {
1326
+		select {
1327
+		case <-ticker.C:
1328
+			conn, err := p.connSelector.LeaderConn(ctx)
1329
+			if err != nil {
1330
+				return nil, err
1331
+			}
1332
+
1333
+			client := NewHealthClient(conn)
1334
+
1335
+			resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"})
1336
+			if err != nil || resp.Status != HealthCheckResponse_SERVING {
1337
+				continue
1338
+			}
1339
+			return conn, nil
1340
+		case <-ctx.Done():
1341
+			return nil, ctx.Err()
1342
+		}
1343
+	}
1344
+}
1345
+
1346
+func (p *raftProxyLogsServer) SubscribeLogs(r *SubscribeLogsRequest, stream Logs_SubscribeLogsServer) error {
1347
+
1348
+	ctx := stream.Context()
1349
+	conn, err := p.connSelector.LeaderConn(ctx)
1350
+	if err != nil {
1351
+		if err == raftselector.ErrIsLeader {
1352
+			return p.local.SubscribeLogs(r, stream)
1353
+		}
1354
+		return err
1355
+	}
1356
+	ctx, err = p.runCtxMods(ctx)
1357
+	if err != nil {
1358
+		return err
1359
+	}
1360
+	clientStream, err := NewLogsClient(conn).SubscribeLogs(ctx, r)
1361
+
1362
+	if err != nil {
1363
+		return err
1364
+	}
1365
+
1366
+	for {
1367
+		msg, err := clientStream.Recv()
1368
+		if err == io.EOF {
1369
+			break
1370
+		}
1371
+		if err != nil {
1372
+			return err
1373
+		}
1374
+		if err := stream.Send(msg); err != nil {
1375
+			return err
1376
+		}
1377
+	}
1378
+	return nil
1379
+}
1380
+
1381
+type raftProxyLogBrokerServer struct {
1382
+	local        LogBrokerServer
1383
+	connSelector raftselector.ConnProvider
1384
+	ctxMods      []func(context.Context) (context.Context, error)
1385
+}
1386
+
1387
+func NewRaftProxyLogBrokerServer(local LogBrokerServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) LogBrokerServer {
1388
+	redirectChecker := func(ctx context.Context) (context.Context, error) {
1389
+		s, ok := transport.StreamFromContext(ctx)
1390
+		if !ok {
1391
+			return ctx, grpc.Errorf(codes.InvalidArgument, "remote addr is not found in context")
1392
+		}
1393
+		addr := s.ServerTransport().RemoteAddr().String()
1394
+		md, ok := metadata.FromContext(ctx)
1395
+		if ok && len(md["redirect"]) != 0 {
1396
+			return ctx, grpc.Errorf(codes.ResourceExhausted, "more than one redirect to leader from: %s", md["redirect"])
1397
+		}
1398
+		if !ok {
1399
+			md = metadata.New(map[string]string{})
1400
+		}
1401
+		md["redirect"] = append(md["redirect"], addr)
1402
+		return metadata.NewContext(ctx, md), nil
1403
+	}
1404
+	mods := []func(context.Context) (context.Context, error){redirectChecker}
1405
+	mods = append(mods, ctxMod)
1406
+
1407
+	return &raftProxyLogBrokerServer{
1408
+		local:        local,
1409
+		connSelector: connSelector,
1410
+		ctxMods:      mods,
1411
+	}
1412
+}
1413
+func (p *raftProxyLogBrokerServer) runCtxMods(ctx context.Context) (context.Context, error) {
1414
+	var err error
1415
+	for _, mod := range p.ctxMods {
1416
+		ctx, err = mod(ctx)
1417
+		if err != nil {
1418
+			return ctx, err
1419
+		}
1420
+	}
1421
+	return ctx, nil
1422
+}
1423
+func (p *raftProxyLogBrokerServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) {
1424
+	ticker := time.NewTicker(500 * time.Millisecond)
1425
+	defer ticker.Stop()
1426
+	for {
1427
+		select {
1428
+		case <-ticker.C:
1429
+			conn, err := p.connSelector.LeaderConn(ctx)
1430
+			if err != nil {
1431
+				return nil, err
1432
+			}
1433
+
1434
+			client := NewHealthClient(conn)
1435
+
1436
+			resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"})
1437
+			if err != nil || resp.Status != HealthCheckResponse_SERVING {
1438
+				continue
1439
+			}
1440
+			return conn, nil
1441
+		case <-ctx.Done():
1442
+			return nil, ctx.Err()
1443
+		}
1444
+	}
1445
+}
1446
+
1447
+func (p *raftProxyLogBrokerServer) ListenSubscriptions(r *ListenSubscriptionsRequest, stream LogBroker_ListenSubscriptionsServer) error {
1448
+
1449
+	ctx := stream.Context()
1450
+	conn, err := p.connSelector.LeaderConn(ctx)
1451
+	if err != nil {
1452
+		if err == raftselector.ErrIsLeader {
1453
+			return p.local.ListenSubscriptions(r, stream)
1454
+		}
1455
+		return err
1456
+	}
1457
+	ctx, err = p.runCtxMods(ctx)
1458
+	if err != nil {
1459
+		return err
1460
+	}
1461
+	clientStream, err := NewLogBrokerClient(conn).ListenSubscriptions(ctx, r)
1462
+
1463
+	if err != nil {
1464
+		return err
1465
+	}
1466
+
1467
+	for {
1468
+		msg, err := clientStream.Recv()
1469
+		if err == io.EOF {
1470
+			break
1471
+		}
1472
+		if err != nil {
1473
+			return err
1474
+		}
1475
+		if err := stream.Send(msg); err != nil {
1476
+			return err
1477
+		}
1478
+	}
1479
+	return nil
1480
+}
1481
+
1482
+func (p *raftProxyLogBrokerServer) PublishLogs(stream LogBroker_PublishLogsServer) error {
1483
+
1484
+	ctx := stream.Context()
1485
+	conn, err := p.connSelector.LeaderConn(ctx)
1486
+	if err != nil {
1487
+		if err == raftselector.ErrIsLeader {
1488
+			return p.local.PublishLogs(stream)
1489
+		}
1490
+		return err
1491
+	}
1492
+	ctx, err = p.runCtxMods(ctx)
1493
+	if err != nil {
1494
+		return err
1495
+	}
1496
+	clientStream, err := NewLogBrokerClient(conn).PublishLogs(ctx)
1497
+
1498
+	if err != nil {
1499
+		return err
1500
+	}
1501
+
1502
+	for {
1503
+		msg, err := stream.Recv()
1504
+		if err == io.EOF {
1505
+			break
1506
+		}
1507
+		if err != nil {
1508
+			return err
1509
+		}
1510
+		if err := clientStream.Send(msg); err != nil {
1511
+			return err
1512
+		}
1513
+	}
1514
+
1515
+	reply, err := clientStream.CloseAndRecv()
1516
+	if err != nil {
1517
+		return err
1518
+	}
1519
+
1520
+	return stream.SendAndClose(reply)
1521
+}
1522
+
1523
+func (m *LogSubscriptionOptions) Size() (n int) {
1524
+	var l int
1525
+	_ = l
1526
+	if len(m.Streams) > 0 {
1527
+		for _, e := range m.Streams {
1528
+			n += 1 + sovLogbroker(uint64(e))
1529
+		}
1530
+	}
1531
+	if m.Follow {
1532
+		n += 2
1533
+	}
1534
+	if m.Tail != 0 {
1535
+		n += 1 + sovLogbroker(uint64(m.Tail))
1536
+	}
1537
+	if m.Since != nil {
1538
+		l = m.Since.Size()
1539
+		n += 1 + l + sovLogbroker(uint64(l))
1540
+	}
1541
+	return n
1542
+}
1543
+
1544
+func (m *LogSelector) Size() (n int) {
1545
+	var l int
1546
+	_ = l
1547
+	if len(m.ServiceIDs) > 0 {
1548
+		for _, s := range m.ServiceIDs {
1549
+			l = len(s)
1550
+			n += 1 + l + sovLogbroker(uint64(l))
1551
+		}
1552
+	}
1553
+	if len(m.NodeIDs) > 0 {
1554
+		for _, s := range m.NodeIDs {
1555
+			l = len(s)
1556
+			n += 1 + l + sovLogbroker(uint64(l))
1557
+		}
1558
+	}
1559
+	if len(m.TaskIDs) > 0 {
1560
+		for _, s := range m.TaskIDs {
1561
+			l = len(s)
1562
+			n += 1 + l + sovLogbroker(uint64(l))
1563
+		}
1564
+	}
1565
+	return n
1566
+}
1567
+
1568
+func (m *LogContext) Size() (n int) {
1569
+	var l int
1570
+	_ = l
1571
+	l = len(m.ServiceID)
1572
+	if l > 0 {
1573
+		n += 1 + l + sovLogbroker(uint64(l))
1574
+	}
1575
+	l = len(m.NodeID)
1576
+	if l > 0 {
1577
+		n += 1 + l + sovLogbroker(uint64(l))
1578
+	}
1579
+	l = len(m.TaskID)
1580
+	if l > 0 {
1581
+		n += 1 + l + sovLogbroker(uint64(l))
1582
+	}
1583
+	return n
1584
+}
1585
+
1586
+func (m *LogMessage) Size() (n int) {
1587
+	var l int
1588
+	_ = l
1589
+	l = m.Context.Size()
1590
+	n += 1 + l + sovLogbroker(uint64(l))
1591
+	if m.Timestamp != nil {
1592
+		l = m.Timestamp.Size()
1593
+		n += 1 + l + sovLogbroker(uint64(l))
1594
+	}
1595
+	if m.Stream != 0 {
1596
+		n += 1 + sovLogbroker(uint64(m.Stream))
1597
+	}
1598
+	l = len(m.Data)
1599
+	if l > 0 {
1600
+		n += 1 + l + sovLogbroker(uint64(l))
1601
+	}
1602
+	return n
1603
+}
1604
+
1605
+func (m *SubscribeLogsRequest) Size() (n int) {
1606
+	var l int
1607
+	_ = l
1608
+	if m.Selector != nil {
1609
+		l = m.Selector.Size()
1610
+		n += 1 + l + sovLogbroker(uint64(l))
1611
+	}
1612
+	if m.Options != nil {
1613
+		l = m.Options.Size()
1614
+		n += 1 + l + sovLogbroker(uint64(l))
1615
+	}
1616
+	return n
1617
+}
1618
+
1619
+func (m *SubscribeLogsMessage) Size() (n int) {
1620
+	var l int
1621
+	_ = l
1622
+	if len(m.Messages) > 0 {
1623
+		for _, e := range m.Messages {
1624
+			l = e.Size()
1625
+			n += 1 + l + sovLogbroker(uint64(l))
1626
+		}
1627
+	}
1628
+	return n
1629
+}
1630
+
1631
+func (m *ListenSubscriptionsRequest) Size() (n int) {
1632
+	var l int
1633
+	_ = l
1634
+	return n
1635
+}
1636
+
1637
+func (m *SubscriptionMessage) Size() (n int) {
1638
+	var l int
1639
+	_ = l
1640
+	l = len(m.ID)
1641
+	if l > 0 {
1642
+		n += 1 + l + sovLogbroker(uint64(l))
1643
+	}
1644
+	if m.Selector != nil {
1645
+		l = m.Selector.Size()
1646
+		n += 1 + l + sovLogbroker(uint64(l))
1647
+	}
1648
+	if m.Options != nil {
1649
+		l = m.Options.Size()
1650
+		n += 1 + l + sovLogbroker(uint64(l))
1651
+	}
1652
+	if m.Close {
1653
+		n += 2
1654
+	}
1655
+	return n
1656
+}
1657
+
1658
+func (m *PublishLogsMessage) Size() (n int) {
1659
+	var l int
1660
+	_ = l
1661
+	l = len(m.SubscriptionID)
1662
+	if l > 0 {
1663
+		n += 1 + l + sovLogbroker(uint64(l))
1664
+	}
1665
+	if len(m.Messages) > 0 {
1666
+		for _, e := range m.Messages {
1667
+			l = e.Size()
1668
+			n += 1 + l + sovLogbroker(uint64(l))
1669
+		}
1670
+	}
1671
+	return n
1672
+}
1673
+
1674
+func (m *PublishLogsResponse) Size() (n int) {
1675
+	var l int
1676
+	_ = l
1677
+	return n
1678
+}
1679
+
1680
+func sovLogbroker(x uint64) (n int) {
1681
+	for {
1682
+		n++
1683
+		x >>= 7
1684
+		if x == 0 {
1685
+			break
1686
+		}
1687
+	}
1688
+	return n
1689
+}
1690
+func sozLogbroker(x uint64) (n int) {
1691
+	return sovLogbroker(uint64((x << 1) ^ uint64((int64(x) >> 63))))
1692
+}
1693
+func (this *LogSubscriptionOptions) String() string {
1694
+	if this == nil {
1695
+		return "nil"
1696
+	}
1697
+	s := strings.Join([]string{`&LogSubscriptionOptions{`,
1698
+		`Streams:` + fmt.Sprintf("%v", this.Streams) + `,`,
1699
+		`Follow:` + fmt.Sprintf("%v", this.Follow) + `,`,
1700
+		`Tail:` + fmt.Sprintf("%v", this.Tail) + `,`,
1701
+		`Since:` + strings.Replace(fmt.Sprintf("%v", this.Since), "Timestamp", "docker_swarmkit_v1.Timestamp", 1) + `,`,
1702
+		`}`,
1703
+	}, "")
1704
+	return s
1705
+}
1706
+func (this *LogSelector) String() string {
1707
+	if this == nil {
1708
+		return "nil"
1709
+	}
1710
+	s := strings.Join([]string{`&LogSelector{`,
1711
+		`ServiceIDs:` + fmt.Sprintf("%v", this.ServiceIDs) + `,`,
1712
+		`NodeIDs:` + fmt.Sprintf("%v", this.NodeIDs) + `,`,
1713
+		`TaskIDs:` + fmt.Sprintf("%v", this.TaskIDs) + `,`,
1714
+		`}`,
1715
+	}, "")
1716
+	return s
1717
+}
1718
+func (this *LogContext) String() string {
1719
+	if this == nil {
1720
+		return "nil"
1721
+	}
1722
+	s := strings.Join([]string{`&LogContext{`,
1723
+		`ServiceID:` + fmt.Sprintf("%v", this.ServiceID) + `,`,
1724
+		`NodeID:` + fmt.Sprintf("%v", this.NodeID) + `,`,
1725
+		`TaskID:` + fmt.Sprintf("%v", this.TaskID) + `,`,
1726
+		`}`,
1727
+	}, "")
1728
+	return s
1729
+}
1730
+func (this *LogMessage) String() string {
1731
+	if this == nil {
1732
+		return "nil"
1733
+	}
1734
+	s := strings.Join([]string{`&LogMessage{`,
1735
+		`Context:` + strings.Replace(strings.Replace(this.Context.String(), "LogContext", "LogContext", 1), `&`, ``, 1) + `,`,
1736
+		`Timestamp:` + strings.Replace(fmt.Sprintf("%v", this.Timestamp), "Timestamp", "docker_swarmkit_v1.Timestamp", 1) + `,`,
1737
+		`Stream:` + fmt.Sprintf("%v", this.Stream) + `,`,
1738
+		`Data:` + fmt.Sprintf("%v", this.Data) + `,`,
1739
+		`}`,
1740
+	}, "")
1741
+	return s
1742
+}
1743
+func (this *SubscribeLogsRequest) String() string {
1744
+	if this == nil {
1745
+		return "nil"
1746
+	}
1747
+	s := strings.Join([]string{`&SubscribeLogsRequest{`,
1748
+		`Selector:` + strings.Replace(fmt.Sprintf("%v", this.Selector), "LogSelector", "LogSelector", 1) + `,`,
1749
+		`Options:` + strings.Replace(fmt.Sprintf("%v", this.Options), "LogSubscriptionOptions", "LogSubscriptionOptions", 1) + `,`,
1750
+		`}`,
1751
+	}, "")
1752
+	return s
1753
+}
1754
+func (this *SubscribeLogsMessage) String() string {
1755
+	if this == nil {
1756
+		return "nil"
1757
+	}
1758
+	s := strings.Join([]string{`&SubscribeLogsMessage{`,
1759
+		`Messages:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Messages), "LogMessage", "LogMessage", 1), `&`, ``, 1) + `,`,
1760
+		`}`,
1761
+	}, "")
1762
+	return s
1763
+}
1764
+func (this *ListenSubscriptionsRequest) String() string {
1765
+	if this == nil {
1766
+		return "nil"
1767
+	}
1768
+	s := strings.Join([]string{`&ListenSubscriptionsRequest{`,
1769
+		`}`,
1770
+	}, "")
1771
+	return s
1772
+}
1773
+func (this *SubscriptionMessage) String() string {
1774
+	if this == nil {
1775
+		return "nil"
1776
+	}
1777
+	s := strings.Join([]string{`&SubscriptionMessage{`,
1778
+		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
1779
+		`Selector:` + strings.Replace(fmt.Sprintf("%v", this.Selector), "LogSelector", "LogSelector", 1) + `,`,
1780
+		`Options:` + strings.Replace(fmt.Sprintf("%v", this.Options), "LogSubscriptionOptions", "LogSubscriptionOptions", 1) + `,`,
1781
+		`Close:` + fmt.Sprintf("%v", this.Close) + `,`,
1782
+		`}`,
1783
+	}, "")
1784
+	return s
1785
+}
1786
+func (this *PublishLogsMessage) String() string {
1787
+	if this == nil {
1788
+		return "nil"
1789
+	}
1790
+	s := strings.Join([]string{`&PublishLogsMessage{`,
1791
+		`SubscriptionID:` + fmt.Sprintf("%v", this.SubscriptionID) + `,`,
1792
+		`Messages:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Messages), "LogMessage", "LogMessage", 1), `&`, ``, 1) + `,`,
1793
+		`}`,
1794
+	}, "")
1795
+	return s
1796
+}
1797
+func (this *PublishLogsResponse) String() string {
1798
+	if this == nil {
1799
+		return "nil"
1800
+	}
1801
+	s := strings.Join([]string{`&PublishLogsResponse{`,
1802
+		`}`,
1803
+	}, "")
1804
+	return s
1805
+}
1806
+func valueToStringLogbroker(v interface{}) string {
1807
+	rv := reflect.ValueOf(v)
1808
+	if rv.IsNil() {
1809
+		return "nil"
1810
+	}
1811
+	pv := reflect.Indirect(rv).Interface()
1812
+	return fmt.Sprintf("*%v", pv)
1813
+}
1814
+func (m *LogSubscriptionOptions) Unmarshal(data []byte) error {
1815
+	l := len(data)
1816
+	iNdEx := 0
1817
+	for iNdEx < l {
1818
+		preIndex := iNdEx
1819
+		var wire uint64
1820
+		for shift := uint(0); ; shift += 7 {
1821
+			if shift >= 64 {
1822
+				return ErrIntOverflowLogbroker
1823
+			}
1824
+			if iNdEx >= l {
1825
+				return io.ErrUnexpectedEOF
1826
+			}
1827
+			b := data[iNdEx]
1828
+			iNdEx++
1829
+			wire |= (uint64(b) & 0x7F) << shift
1830
+			if b < 0x80 {
1831
+				break
1832
+			}
1833
+		}
1834
+		fieldNum := int32(wire >> 3)
1835
+		wireType := int(wire & 0x7)
1836
+		if wireType == 4 {
1837
+			return fmt.Errorf("proto: LogSubscriptionOptions: wiretype end group for non-group")
1838
+		}
1839
+		if fieldNum <= 0 {
1840
+			return fmt.Errorf("proto: LogSubscriptionOptions: illegal tag %d (wire type %d)", fieldNum, wire)
1841
+		}
1842
+		switch fieldNum {
1843
+		case 1:
1844
+			if wireType != 0 {
1845
+				return fmt.Errorf("proto: wrong wireType = %d for field Streams", wireType)
1846
+			}
1847
+			var v LogStream
1848
+			for shift := uint(0); ; shift += 7 {
1849
+				if shift >= 64 {
1850
+					return ErrIntOverflowLogbroker
1851
+				}
1852
+				if iNdEx >= l {
1853
+					return io.ErrUnexpectedEOF
1854
+				}
1855
+				b := data[iNdEx]
1856
+				iNdEx++
1857
+				v |= (LogStream(b) & 0x7F) << shift
1858
+				if b < 0x80 {
1859
+					break
1860
+				}
1861
+			}
1862
+			m.Streams = append(m.Streams, v)
1863
+		case 2:
1864
+			if wireType != 0 {
1865
+				return fmt.Errorf("proto: wrong wireType = %d for field Follow", wireType)
1866
+			}
1867
+			var v int
1868
+			for shift := uint(0); ; shift += 7 {
1869
+				if shift >= 64 {
1870
+					return ErrIntOverflowLogbroker
1871
+				}
1872
+				if iNdEx >= l {
1873
+					return io.ErrUnexpectedEOF
1874
+				}
1875
+				b := data[iNdEx]
1876
+				iNdEx++
1877
+				v |= (int(b) & 0x7F) << shift
1878
+				if b < 0x80 {
1879
+					break
1880
+				}
1881
+			}
1882
+			m.Follow = bool(v != 0)
1883
+		case 3:
1884
+			if wireType != 0 {
1885
+				return fmt.Errorf("proto: wrong wireType = %d for field Tail", wireType)
1886
+			}
1887
+			m.Tail = 0
1888
+			for shift := uint(0); ; shift += 7 {
1889
+				if shift >= 64 {
1890
+					return ErrIntOverflowLogbroker
1891
+				}
1892
+				if iNdEx >= l {
1893
+					return io.ErrUnexpectedEOF
1894
+				}
1895
+				b := data[iNdEx]
1896
+				iNdEx++
1897
+				m.Tail |= (int64(b) & 0x7F) << shift
1898
+				if b < 0x80 {
1899
+					break
1900
+				}
1901
+			}
1902
+		case 4:
1903
+			if wireType != 2 {
1904
+				return fmt.Errorf("proto: wrong wireType = %d for field Since", wireType)
1905
+			}
1906
+			var msglen int
1907
+			for shift := uint(0); ; shift += 7 {
1908
+				if shift >= 64 {
1909
+					return ErrIntOverflowLogbroker
1910
+				}
1911
+				if iNdEx >= l {
1912
+					return io.ErrUnexpectedEOF
1913
+				}
1914
+				b := data[iNdEx]
1915
+				iNdEx++
1916
+				msglen |= (int(b) & 0x7F) << shift
1917
+				if b < 0x80 {
1918
+					break
1919
+				}
1920
+			}
1921
+			if msglen < 0 {
1922
+				return ErrInvalidLengthLogbroker
1923
+			}
1924
+			postIndex := iNdEx + msglen
1925
+			if postIndex > l {
1926
+				return io.ErrUnexpectedEOF
1927
+			}
1928
+			if m.Since == nil {
1929
+				m.Since = &docker_swarmkit_v1.Timestamp{}
1930
+			}
1931
+			if err := m.Since.Unmarshal(data[iNdEx:postIndex]); err != nil {
1932
+				return err
1933
+			}
1934
+			iNdEx = postIndex
1935
+		default:
1936
+			iNdEx = preIndex
1937
+			skippy, err := skipLogbroker(data[iNdEx:])
1938
+			if err != nil {
1939
+				return err
1940
+			}
1941
+			if skippy < 0 {
1942
+				return ErrInvalidLengthLogbroker
1943
+			}
1944
+			if (iNdEx + skippy) > l {
1945
+				return io.ErrUnexpectedEOF
1946
+			}
1947
+			iNdEx += skippy
1948
+		}
1949
+	}
1950
+
1951
+	if iNdEx > l {
1952
+		return io.ErrUnexpectedEOF
1953
+	}
1954
+	return nil
1955
+}
1956
+func (m *LogSelector) Unmarshal(data []byte) error {
1957
+	l := len(data)
1958
+	iNdEx := 0
1959
+	for iNdEx < l {
1960
+		preIndex := iNdEx
1961
+		var wire uint64
1962
+		for shift := uint(0); ; shift += 7 {
1963
+			if shift >= 64 {
1964
+				return ErrIntOverflowLogbroker
1965
+			}
1966
+			if iNdEx >= l {
1967
+				return io.ErrUnexpectedEOF
1968
+			}
1969
+			b := data[iNdEx]
1970
+			iNdEx++
1971
+			wire |= (uint64(b) & 0x7F) << shift
1972
+			if b < 0x80 {
1973
+				break
1974
+			}
1975
+		}
1976
+		fieldNum := int32(wire >> 3)
1977
+		wireType := int(wire & 0x7)
1978
+		if wireType == 4 {
1979
+			return fmt.Errorf("proto: LogSelector: wiretype end group for non-group")
1980
+		}
1981
+		if fieldNum <= 0 {
1982
+			return fmt.Errorf("proto: LogSelector: illegal tag %d (wire type %d)", fieldNum, wire)
1983
+		}
1984
+		switch fieldNum {
1985
+		case 1:
1986
+			if wireType != 2 {
1987
+				return fmt.Errorf("proto: wrong wireType = %d for field ServiceIDs", wireType)
1988
+			}
1989
+			var stringLen uint64
1990
+			for shift := uint(0); ; shift += 7 {
1991
+				if shift >= 64 {
1992
+					return ErrIntOverflowLogbroker
1993
+				}
1994
+				if iNdEx >= l {
1995
+					return io.ErrUnexpectedEOF
1996
+				}
1997
+				b := data[iNdEx]
1998
+				iNdEx++
1999
+				stringLen |= (uint64(b) & 0x7F) << shift
2000
+				if b < 0x80 {
2001
+					break
2002
+				}
2003
+			}
2004
+			intStringLen := int(stringLen)
2005
+			if intStringLen < 0 {
2006
+				return ErrInvalidLengthLogbroker
2007
+			}
2008
+			postIndex := iNdEx + intStringLen
2009
+			if postIndex > l {
2010
+				return io.ErrUnexpectedEOF
2011
+			}
2012
+			m.ServiceIDs = append(m.ServiceIDs, string(data[iNdEx:postIndex]))
2013
+			iNdEx = postIndex
2014
+		case 2:
2015
+			if wireType != 2 {
2016
+				return fmt.Errorf("proto: wrong wireType = %d for field NodeIDs", wireType)
2017
+			}
2018
+			var stringLen uint64
2019
+			for shift := uint(0); ; shift += 7 {
2020
+				if shift >= 64 {
2021
+					return ErrIntOverflowLogbroker
2022
+				}
2023
+				if iNdEx >= l {
2024
+					return io.ErrUnexpectedEOF
2025
+				}
2026
+				b := data[iNdEx]
2027
+				iNdEx++
2028
+				stringLen |= (uint64(b) & 0x7F) << shift
2029
+				if b < 0x80 {
2030
+					break
2031
+				}
2032
+			}
2033
+			intStringLen := int(stringLen)
2034
+			if intStringLen < 0 {
2035
+				return ErrInvalidLengthLogbroker
2036
+			}
2037
+			postIndex := iNdEx + intStringLen
2038
+			if postIndex > l {
2039
+				return io.ErrUnexpectedEOF
2040
+			}
2041
+			m.NodeIDs = append(m.NodeIDs, string(data[iNdEx:postIndex]))
2042
+			iNdEx = postIndex
2043
+		case 3:
2044
+			if wireType != 2 {
2045
+				return fmt.Errorf("proto: wrong wireType = %d for field TaskIDs", wireType)
2046
+			}
2047
+			var stringLen uint64
2048
+			for shift := uint(0); ; shift += 7 {
2049
+				if shift >= 64 {
2050
+					return ErrIntOverflowLogbroker
2051
+				}
2052
+				if iNdEx >= l {
2053
+					return io.ErrUnexpectedEOF
2054
+				}
2055
+				b := data[iNdEx]
2056
+				iNdEx++
2057
+				stringLen |= (uint64(b) & 0x7F) << shift
2058
+				if b < 0x80 {
2059
+					break
2060
+				}
2061
+			}
2062
+			intStringLen := int(stringLen)
2063
+			if intStringLen < 0 {
2064
+				return ErrInvalidLengthLogbroker
2065
+			}
2066
+			postIndex := iNdEx + intStringLen
2067
+			if postIndex > l {
2068
+				return io.ErrUnexpectedEOF
2069
+			}
2070
+			m.TaskIDs = append(m.TaskIDs, string(data[iNdEx:postIndex]))
2071
+			iNdEx = postIndex
2072
+		default:
2073
+			iNdEx = preIndex
2074
+			skippy, err := skipLogbroker(data[iNdEx:])
2075
+			if err != nil {
2076
+				return err
2077
+			}
2078
+			if skippy < 0 {
2079
+				return ErrInvalidLengthLogbroker
2080
+			}
2081
+			if (iNdEx + skippy) > l {
2082
+				return io.ErrUnexpectedEOF
2083
+			}
2084
+			iNdEx += skippy
2085
+		}
2086
+	}
2087
+
2088
+	if iNdEx > l {
2089
+		return io.ErrUnexpectedEOF
2090
+	}
2091
+	return nil
2092
+}
2093
+func (m *LogContext) Unmarshal(data []byte) error {
2094
+	l := len(data)
2095
+	iNdEx := 0
2096
+	for iNdEx < l {
2097
+		preIndex := iNdEx
2098
+		var wire uint64
2099
+		for shift := uint(0); ; shift += 7 {
2100
+			if shift >= 64 {
2101
+				return ErrIntOverflowLogbroker
2102
+			}
2103
+			if iNdEx >= l {
2104
+				return io.ErrUnexpectedEOF
2105
+			}
2106
+			b := data[iNdEx]
2107
+			iNdEx++
2108
+			wire |= (uint64(b) & 0x7F) << shift
2109
+			if b < 0x80 {
2110
+				break
2111
+			}
2112
+		}
2113
+		fieldNum := int32(wire >> 3)
2114
+		wireType := int(wire & 0x7)
2115
+		if wireType == 4 {
2116
+			return fmt.Errorf("proto: LogContext: wiretype end group for non-group")
2117
+		}
2118
+		if fieldNum <= 0 {
2119
+			return fmt.Errorf("proto: LogContext: illegal tag %d (wire type %d)", fieldNum, wire)
2120
+		}
2121
+		switch fieldNum {
2122
+		case 1:
2123
+			if wireType != 2 {
2124
+				return fmt.Errorf("proto: wrong wireType = %d for field ServiceID", wireType)
2125
+			}
2126
+			var stringLen uint64
2127
+			for shift := uint(0); ; shift += 7 {
2128
+				if shift >= 64 {
2129
+					return ErrIntOverflowLogbroker
2130
+				}
2131
+				if iNdEx >= l {
2132
+					return io.ErrUnexpectedEOF
2133
+				}
2134
+				b := data[iNdEx]
2135
+				iNdEx++
2136
+				stringLen |= (uint64(b) & 0x7F) << shift
2137
+				if b < 0x80 {
2138
+					break
2139
+				}
2140
+			}
2141
+			intStringLen := int(stringLen)
2142
+			if intStringLen < 0 {
2143
+				return ErrInvalidLengthLogbroker
2144
+			}
2145
+			postIndex := iNdEx + intStringLen
2146
+			if postIndex > l {
2147
+				return io.ErrUnexpectedEOF
2148
+			}
2149
+			m.ServiceID = string(data[iNdEx:postIndex])
2150
+			iNdEx = postIndex
2151
+		case 2:
2152
+			if wireType != 2 {
2153
+				return fmt.Errorf("proto: wrong wireType = %d for field NodeID", wireType)
2154
+			}
2155
+			var stringLen uint64
2156
+			for shift := uint(0); ; shift += 7 {
2157
+				if shift >= 64 {
2158
+					return ErrIntOverflowLogbroker
2159
+				}
2160
+				if iNdEx >= l {
2161
+					return io.ErrUnexpectedEOF
2162
+				}
2163
+				b := data[iNdEx]
2164
+				iNdEx++
2165
+				stringLen |= (uint64(b) & 0x7F) << shift
2166
+				if b < 0x80 {
2167
+					break
2168
+				}
2169
+			}
2170
+			intStringLen := int(stringLen)
2171
+			if intStringLen < 0 {
2172
+				return ErrInvalidLengthLogbroker
2173
+			}
2174
+			postIndex := iNdEx + intStringLen
2175
+			if postIndex > l {
2176
+				return io.ErrUnexpectedEOF
2177
+			}
2178
+			m.NodeID = string(data[iNdEx:postIndex])
2179
+			iNdEx = postIndex
2180
+		case 3:
2181
+			if wireType != 2 {
2182
+				return fmt.Errorf("proto: wrong wireType = %d for field TaskID", wireType)
2183
+			}
2184
+			var stringLen uint64
2185
+			for shift := uint(0); ; shift += 7 {
2186
+				if shift >= 64 {
2187
+					return ErrIntOverflowLogbroker
2188
+				}
2189
+				if iNdEx >= l {
2190
+					return io.ErrUnexpectedEOF
2191
+				}
2192
+				b := data[iNdEx]
2193
+				iNdEx++
2194
+				stringLen |= (uint64(b) & 0x7F) << shift
2195
+				if b < 0x80 {
2196
+					break
2197
+				}
2198
+			}
2199
+			intStringLen := int(stringLen)
2200
+			if intStringLen < 0 {
2201
+				return ErrInvalidLengthLogbroker
2202
+			}
2203
+			postIndex := iNdEx + intStringLen
2204
+			if postIndex > l {
2205
+				return io.ErrUnexpectedEOF
2206
+			}
2207
+			m.TaskID = string(data[iNdEx:postIndex])
2208
+			iNdEx = postIndex
2209
+		default:
2210
+			iNdEx = preIndex
2211
+			skippy, err := skipLogbroker(data[iNdEx:])
2212
+			if err != nil {
2213
+				return err
2214
+			}
2215
+			if skippy < 0 {
2216
+				return ErrInvalidLengthLogbroker
2217
+			}
2218
+			if (iNdEx + skippy) > l {
2219
+				return io.ErrUnexpectedEOF
2220
+			}
2221
+			iNdEx += skippy
2222
+		}
2223
+	}
2224
+
2225
+	if iNdEx > l {
2226
+		return io.ErrUnexpectedEOF
2227
+	}
2228
+	return nil
2229
+}
2230
+func (m *LogMessage) Unmarshal(data []byte) error {
2231
+	l := len(data)
2232
+	iNdEx := 0
2233
+	for iNdEx < l {
2234
+		preIndex := iNdEx
2235
+		var wire uint64
2236
+		for shift := uint(0); ; shift += 7 {
2237
+			if shift >= 64 {
2238
+				return ErrIntOverflowLogbroker
2239
+			}
2240
+			if iNdEx >= l {
2241
+				return io.ErrUnexpectedEOF
2242
+			}
2243
+			b := data[iNdEx]
2244
+			iNdEx++
2245
+			wire |= (uint64(b) & 0x7F) << shift
2246
+			if b < 0x80 {
2247
+				break
2248
+			}
2249
+		}
2250
+		fieldNum := int32(wire >> 3)
2251
+		wireType := int(wire & 0x7)
2252
+		if wireType == 4 {
2253
+			return fmt.Errorf("proto: LogMessage: wiretype end group for non-group")
2254
+		}
2255
+		if fieldNum <= 0 {
2256
+			return fmt.Errorf("proto: LogMessage: illegal tag %d (wire type %d)", fieldNum, wire)
2257
+		}
2258
+		switch fieldNum {
2259
+		case 1:
2260
+			if wireType != 2 {
2261
+				return fmt.Errorf("proto: wrong wireType = %d for field Context", wireType)
2262
+			}
2263
+			var msglen int
2264
+			for shift := uint(0); ; shift += 7 {
2265
+				if shift >= 64 {
2266
+					return ErrIntOverflowLogbroker
2267
+				}
2268
+				if iNdEx >= l {
2269
+					return io.ErrUnexpectedEOF
2270
+				}
2271
+				b := data[iNdEx]
2272
+				iNdEx++
2273
+				msglen |= (int(b) & 0x7F) << shift
2274
+				if b < 0x80 {
2275
+					break
2276
+				}
2277
+			}
2278
+			if msglen < 0 {
2279
+				return ErrInvalidLengthLogbroker
2280
+			}
2281
+			postIndex := iNdEx + msglen
2282
+			if postIndex > l {
2283
+				return io.ErrUnexpectedEOF
2284
+			}
2285
+			if err := m.Context.Unmarshal(data[iNdEx:postIndex]); err != nil {
2286
+				return err
2287
+			}
2288
+			iNdEx = postIndex
2289
+		case 2:
2290
+			if wireType != 2 {
2291
+				return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
2292
+			}
2293
+			var msglen int
2294
+			for shift := uint(0); ; shift += 7 {
2295
+				if shift >= 64 {
2296
+					return ErrIntOverflowLogbroker
2297
+				}
2298
+				if iNdEx >= l {
2299
+					return io.ErrUnexpectedEOF
2300
+				}
2301
+				b := data[iNdEx]
2302
+				iNdEx++
2303
+				msglen |= (int(b) & 0x7F) << shift
2304
+				if b < 0x80 {
2305
+					break
2306
+				}
2307
+			}
2308
+			if msglen < 0 {
2309
+				return ErrInvalidLengthLogbroker
2310
+			}
2311
+			postIndex := iNdEx + msglen
2312
+			if postIndex > l {
2313
+				return io.ErrUnexpectedEOF
2314
+			}
2315
+			if m.Timestamp == nil {
2316
+				m.Timestamp = &docker_swarmkit_v1.Timestamp{}
2317
+			}
2318
+			if err := m.Timestamp.Unmarshal(data[iNdEx:postIndex]); err != nil {
2319
+				return err
2320
+			}
2321
+			iNdEx = postIndex
2322
+		case 3:
2323
+			if wireType != 0 {
2324
+				return fmt.Errorf("proto: wrong wireType = %d for field Stream", wireType)
2325
+			}
2326
+			m.Stream = 0
2327
+			for shift := uint(0); ; shift += 7 {
2328
+				if shift >= 64 {
2329
+					return ErrIntOverflowLogbroker
2330
+				}
2331
+				if iNdEx >= l {
2332
+					return io.ErrUnexpectedEOF
2333
+				}
2334
+				b := data[iNdEx]
2335
+				iNdEx++
2336
+				m.Stream |= (LogStream(b) & 0x7F) << shift
2337
+				if b < 0x80 {
2338
+					break
2339
+				}
2340
+			}
2341
+		case 4:
2342
+			if wireType != 2 {
2343
+				return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
2344
+			}
2345
+			var byteLen int
2346
+			for shift := uint(0); ; shift += 7 {
2347
+				if shift >= 64 {
2348
+					return ErrIntOverflowLogbroker
2349
+				}
2350
+				if iNdEx >= l {
2351
+					return io.ErrUnexpectedEOF
2352
+				}
2353
+				b := data[iNdEx]
2354
+				iNdEx++
2355
+				byteLen |= (int(b) & 0x7F) << shift
2356
+				if b < 0x80 {
2357
+					break
2358
+				}
2359
+			}
2360
+			if byteLen < 0 {
2361
+				return ErrInvalidLengthLogbroker
2362
+			}
2363
+			postIndex := iNdEx + byteLen
2364
+			if postIndex > l {
2365
+				return io.ErrUnexpectedEOF
2366
+			}
2367
+			m.Data = append(m.Data[:0], data[iNdEx:postIndex]...)
2368
+			if m.Data == nil {
2369
+				m.Data = []byte{}
2370
+			}
2371
+			iNdEx = postIndex
2372
+		default:
2373
+			iNdEx = preIndex
2374
+			skippy, err := skipLogbroker(data[iNdEx:])
2375
+			if err != nil {
2376
+				return err
2377
+			}
2378
+			if skippy < 0 {
2379
+				return ErrInvalidLengthLogbroker
2380
+			}
2381
+			if (iNdEx + skippy) > l {
2382
+				return io.ErrUnexpectedEOF
2383
+			}
2384
+			iNdEx += skippy
2385
+		}
2386
+	}
2387
+
2388
+	if iNdEx > l {
2389
+		return io.ErrUnexpectedEOF
2390
+	}
2391
+	return nil
2392
+}
2393
+func (m *SubscribeLogsRequest) Unmarshal(data []byte) error {
2394
+	l := len(data)
2395
+	iNdEx := 0
2396
+	for iNdEx < l {
2397
+		preIndex := iNdEx
2398
+		var wire uint64
2399
+		for shift := uint(0); ; shift += 7 {
2400
+			if shift >= 64 {
2401
+				return ErrIntOverflowLogbroker
2402
+			}
2403
+			if iNdEx >= l {
2404
+				return io.ErrUnexpectedEOF
2405
+			}
2406
+			b := data[iNdEx]
2407
+			iNdEx++
2408
+			wire |= (uint64(b) & 0x7F) << shift
2409
+			if b < 0x80 {
2410
+				break
2411
+			}
2412
+		}
2413
+		fieldNum := int32(wire >> 3)
2414
+		wireType := int(wire & 0x7)
2415
+		if wireType == 4 {
2416
+			return fmt.Errorf("proto: SubscribeLogsRequest: wiretype end group for non-group")
2417
+		}
2418
+		if fieldNum <= 0 {
2419
+			return fmt.Errorf("proto: SubscribeLogsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
2420
+		}
2421
+		switch fieldNum {
2422
+		case 1:
2423
+			if wireType != 2 {
2424
+				return fmt.Errorf("proto: wrong wireType = %d for field Selector", wireType)
2425
+			}
2426
+			var msglen int
2427
+			for shift := uint(0); ; shift += 7 {
2428
+				if shift >= 64 {
2429
+					return ErrIntOverflowLogbroker
2430
+				}
2431
+				if iNdEx >= l {
2432
+					return io.ErrUnexpectedEOF
2433
+				}
2434
+				b := data[iNdEx]
2435
+				iNdEx++
2436
+				msglen |= (int(b) & 0x7F) << shift
2437
+				if b < 0x80 {
2438
+					break
2439
+				}
2440
+			}
2441
+			if msglen < 0 {
2442
+				return ErrInvalidLengthLogbroker
2443
+			}
2444
+			postIndex := iNdEx + msglen
2445
+			if postIndex > l {
2446
+				return io.ErrUnexpectedEOF
2447
+			}
2448
+			if m.Selector == nil {
2449
+				m.Selector = &LogSelector{}
2450
+			}
2451
+			if err := m.Selector.Unmarshal(data[iNdEx:postIndex]); err != nil {
2452
+				return err
2453
+			}
2454
+			iNdEx = postIndex
2455
+		case 2:
2456
+			if wireType != 2 {
2457
+				return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
2458
+			}
2459
+			var msglen int
2460
+			for shift := uint(0); ; shift += 7 {
2461
+				if shift >= 64 {
2462
+					return ErrIntOverflowLogbroker
2463
+				}
2464
+				if iNdEx >= l {
2465
+					return io.ErrUnexpectedEOF
2466
+				}
2467
+				b := data[iNdEx]
2468
+				iNdEx++
2469
+				msglen |= (int(b) & 0x7F) << shift
2470
+				if b < 0x80 {
2471
+					break
2472
+				}
2473
+			}
2474
+			if msglen < 0 {
2475
+				return ErrInvalidLengthLogbroker
2476
+			}
2477
+			postIndex := iNdEx + msglen
2478
+			if postIndex > l {
2479
+				return io.ErrUnexpectedEOF
2480
+			}
2481
+			if m.Options == nil {
2482
+				m.Options = &LogSubscriptionOptions{}
2483
+			}
2484
+			if err := m.Options.Unmarshal(data[iNdEx:postIndex]); err != nil {
2485
+				return err
2486
+			}
2487
+			iNdEx = postIndex
2488
+		default:
2489
+			iNdEx = preIndex
2490
+			skippy, err := skipLogbroker(data[iNdEx:])
2491
+			if err != nil {
2492
+				return err
2493
+			}
2494
+			if skippy < 0 {
2495
+				return ErrInvalidLengthLogbroker
2496
+			}
2497
+			if (iNdEx + skippy) > l {
2498
+				return io.ErrUnexpectedEOF
2499
+			}
2500
+			iNdEx += skippy
2501
+		}
2502
+	}
2503
+
2504
+	if iNdEx > l {
2505
+		return io.ErrUnexpectedEOF
2506
+	}
2507
+	return nil
2508
+}
2509
+func (m *SubscribeLogsMessage) Unmarshal(data []byte) error {
2510
+	l := len(data)
2511
+	iNdEx := 0
2512
+	for iNdEx < l {
2513
+		preIndex := iNdEx
2514
+		var wire uint64
2515
+		for shift := uint(0); ; shift += 7 {
2516
+			if shift >= 64 {
2517
+				return ErrIntOverflowLogbroker
2518
+			}
2519
+			if iNdEx >= l {
2520
+				return io.ErrUnexpectedEOF
2521
+			}
2522
+			b := data[iNdEx]
2523
+			iNdEx++
2524
+			wire |= (uint64(b) & 0x7F) << shift
2525
+			if b < 0x80 {
2526
+				break
2527
+			}
2528
+		}
2529
+		fieldNum := int32(wire >> 3)
2530
+		wireType := int(wire & 0x7)
2531
+		if wireType == 4 {
2532
+			return fmt.Errorf("proto: SubscribeLogsMessage: wiretype end group for non-group")
2533
+		}
2534
+		if fieldNum <= 0 {
2535
+			return fmt.Errorf("proto: SubscribeLogsMessage: illegal tag %d (wire type %d)", fieldNum, wire)
2536
+		}
2537
+		switch fieldNum {
2538
+		case 1:
2539
+			if wireType != 2 {
2540
+				return fmt.Errorf("proto: wrong wireType = %d for field Messages", wireType)
2541
+			}
2542
+			var msglen int
2543
+			for shift := uint(0); ; shift += 7 {
2544
+				if shift >= 64 {
2545
+					return ErrIntOverflowLogbroker
2546
+				}
2547
+				if iNdEx >= l {
2548
+					return io.ErrUnexpectedEOF
2549
+				}
2550
+				b := data[iNdEx]
2551
+				iNdEx++
2552
+				msglen |= (int(b) & 0x7F) << shift
2553
+				if b < 0x80 {
2554
+					break
2555
+				}
2556
+			}
2557
+			if msglen < 0 {
2558
+				return ErrInvalidLengthLogbroker
2559
+			}
2560
+			postIndex := iNdEx + msglen
2561
+			if postIndex > l {
2562
+				return io.ErrUnexpectedEOF
2563
+			}
2564
+			m.Messages = append(m.Messages, LogMessage{})
2565
+			if err := m.Messages[len(m.Messages)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
2566
+				return err
2567
+			}
2568
+			iNdEx = postIndex
2569
+		default:
2570
+			iNdEx = preIndex
2571
+			skippy, err := skipLogbroker(data[iNdEx:])
2572
+			if err != nil {
2573
+				return err
2574
+			}
2575
+			if skippy < 0 {
2576
+				return ErrInvalidLengthLogbroker
2577
+			}
2578
+			if (iNdEx + skippy) > l {
2579
+				return io.ErrUnexpectedEOF
2580
+			}
2581
+			iNdEx += skippy
2582
+		}
2583
+	}
2584
+
2585
+	if iNdEx > l {
2586
+		return io.ErrUnexpectedEOF
2587
+	}
2588
+	return nil
2589
+}
2590
+func (m *ListenSubscriptionsRequest) Unmarshal(data []byte) error {
2591
+	l := len(data)
2592
+	iNdEx := 0
2593
+	for iNdEx < l {
2594
+		preIndex := iNdEx
2595
+		var wire uint64
2596
+		for shift := uint(0); ; shift += 7 {
2597
+			if shift >= 64 {
2598
+				return ErrIntOverflowLogbroker
2599
+			}
2600
+			if iNdEx >= l {
2601
+				return io.ErrUnexpectedEOF
2602
+			}
2603
+			b := data[iNdEx]
2604
+			iNdEx++
2605
+			wire |= (uint64(b) & 0x7F) << shift
2606
+			if b < 0x80 {
2607
+				break
2608
+			}
2609
+		}
2610
+		fieldNum := int32(wire >> 3)
2611
+		wireType := int(wire & 0x7)
2612
+		if wireType == 4 {
2613
+			return fmt.Errorf("proto: ListenSubscriptionsRequest: wiretype end group for non-group")
2614
+		}
2615
+		if fieldNum <= 0 {
2616
+			return fmt.Errorf("proto: ListenSubscriptionsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
2617
+		}
2618
+		switch fieldNum {
2619
+		default:
2620
+			iNdEx = preIndex
2621
+			skippy, err := skipLogbroker(data[iNdEx:])
2622
+			if err != nil {
2623
+				return err
2624
+			}
2625
+			if skippy < 0 {
2626
+				return ErrInvalidLengthLogbroker
2627
+			}
2628
+			if (iNdEx + skippy) > l {
2629
+				return io.ErrUnexpectedEOF
2630
+			}
2631
+			iNdEx += skippy
2632
+		}
2633
+	}
2634
+
2635
+	if iNdEx > l {
2636
+		return io.ErrUnexpectedEOF
2637
+	}
2638
+	return nil
2639
+}
2640
+func (m *SubscriptionMessage) Unmarshal(data []byte) error {
2641
+	l := len(data)
2642
+	iNdEx := 0
2643
+	for iNdEx < l {
2644
+		preIndex := iNdEx
2645
+		var wire uint64
2646
+		for shift := uint(0); ; shift += 7 {
2647
+			if shift >= 64 {
2648
+				return ErrIntOverflowLogbroker
2649
+			}
2650
+			if iNdEx >= l {
2651
+				return io.ErrUnexpectedEOF
2652
+			}
2653
+			b := data[iNdEx]
2654
+			iNdEx++
2655
+			wire |= (uint64(b) & 0x7F) << shift
2656
+			if b < 0x80 {
2657
+				break
2658
+			}
2659
+		}
2660
+		fieldNum := int32(wire >> 3)
2661
+		wireType := int(wire & 0x7)
2662
+		if wireType == 4 {
2663
+			return fmt.Errorf("proto: SubscriptionMessage: wiretype end group for non-group")
2664
+		}
2665
+		if fieldNum <= 0 {
2666
+			return fmt.Errorf("proto: SubscriptionMessage: illegal tag %d (wire type %d)", fieldNum, wire)
2667
+		}
2668
+		switch fieldNum {
2669
+		case 1:
2670
+			if wireType != 2 {
2671
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
2672
+			}
2673
+			var stringLen uint64
2674
+			for shift := uint(0); ; shift += 7 {
2675
+				if shift >= 64 {
2676
+					return ErrIntOverflowLogbroker
2677
+				}
2678
+				if iNdEx >= l {
2679
+					return io.ErrUnexpectedEOF
2680
+				}
2681
+				b := data[iNdEx]
2682
+				iNdEx++
2683
+				stringLen |= (uint64(b) & 0x7F) << shift
2684
+				if b < 0x80 {
2685
+					break
2686
+				}
2687
+			}
2688
+			intStringLen := int(stringLen)
2689
+			if intStringLen < 0 {
2690
+				return ErrInvalidLengthLogbroker
2691
+			}
2692
+			postIndex := iNdEx + intStringLen
2693
+			if postIndex > l {
2694
+				return io.ErrUnexpectedEOF
2695
+			}
2696
+			m.ID = string(data[iNdEx:postIndex])
2697
+			iNdEx = postIndex
2698
+		case 2:
2699
+			if wireType != 2 {
2700
+				return fmt.Errorf("proto: wrong wireType = %d for field Selector", wireType)
2701
+			}
2702
+			var msglen int
2703
+			for shift := uint(0); ; shift += 7 {
2704
+				if shift >= 64 {
2705
+					return ErrIntOverflowLogbroker
2706
+				}
2707
+				if iNdEx >= l {
2708
+					return io.ErrUnexpectedEOF
2709
+				}
2710
+				b := data[iNdEx]
2711
+				iNdEx++
2712
+				msglen |= (int(b) & 0x7F) << shift
2713
+				if b < 0x80 {
2714
+					break
2715
+				}
2716
+			}
2717
+			if msglen < 0 {
2718
+				return ErrInvalidLengthLogbroker
2719
+			}
2720
+			postIndex := iNdEx + msglen
2721
+			if postIndex > l {
2722
+				return io.ErrUnexpectedEOF
2723
+			}
2724
+			if m.Selector == nil {
2725
+				m.Selector = &LogSelector{}
2726
+			}
2727
+			if err := m.Selector.Unmarshal(data[iNdEx:postIndex]); err != nil {
2728
+				return err
2729
+			}
2730
+			iNdEx = postIndex
2731
+		case 3:
2732
+			if wireType != 2 {
2733
+				return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
2734
+			}
2735
+			var msglen int
2736
+			for shift := uint(0); ; shift += 7 {
2737
+				if shift >= 64 {
2738
+					return ErrIntOverflowLogbroker
2739
+				}
2740
+				if iNdEx >= l {
2741
+					return io.ErrUnexpectedEOF
2742
+				}
2743
+				b := data[iNdEx]
2744
+				iNdEx++
2745
+				msglen |= (int(b) & 0x7F) << shift
2746
+				if b < 0x80 {
2747
+					break
2748
+				}
2749
+			}
2750
+			if msglen < 0 {
2751
+				return ErrInvalidLengthLogbroker
2752
+			}
2753
+			postIndex := iNdEx + msglen
2754
+			if postIndex > l {
2755
+				return io.ErrUnexpectedEOF
2756
+			}
2757
+			if m.Options == nil {
2758
+				m.Options = &LogSubscriptionOptions{}
2759
+			}
2760
+			if err := m.Options.Unmarshal(data[iNdEx:postIndex]); err != nil {
2761
+				return err
2762
+			}
2763
+			iNdEx = postIndex
2764
+		case 4:
2765
+			if wireType != 0 {
2766
+				return fmt.Errorf("proto: wrong wireType = %d for field Close", wireType)
2767
+			}
2768
+			var v int
2769
+			for shift := uint(0); ; shift += 7 {
2770
+				if shift >= 64 {
2771
+					return ErrIntOverflowLogbroker
2772
+				}
2773
+				if iNdEx >= l {
2774
+					return io.ErrUnexpectedEOF
2775
+				}
2776
+				b := data[iNdEx]
2777
+				iNdEx++
2778
+				v |= (int(b) & 0x7F) << shift
2779
+				if b < 0x80 {
2780
+					break
2781
+				}
2782
+			}
2783
+			m.Close = bool(v != 0)
2784
+		default:
2785
+			iNdEx = preIndex
2786
+			skippy, err := skipLogbroker(data[iNdEx:])
2787
+			if err != nil {
2788
+				return err
2789
+			}
2790
+			if skippy < 0 {
2791
+				return ErrInvalidLengthLogbroker
2792
+			}
2793
+			if (iNdEx + skippy) > l {
2794
+				return io.ErrUnexpectedEOF
2795
+			}
2796
+			iNdEx += skippy
2797
+		}
2798
+	}
2799
+
2800
+	if iNdEx > l {
2801
+		return io.ErrUnexpectedEOF
2802
+	}
2803
+	return nil
2804
+}
2805
+func (m *PublishLogsMessage) Unmarshal(data []byte) error {
2806
+	l := len(data)
2807
+	iNdEx := 0
2808
+	for iNdEx < l {
2809
+		preIndex := iNdEx
2810
+		var wire uint64
2811
+		for shift := uint(0); ; shift += 7 {
2812
+			if shift >= 64 {
2813
+				return ErrIntOverflowLogbroker
2814
+			}
2815
+			if iNdEx >= l {
2816
+				return io.ErrUnexpectedEOF
2817
+			}
2818
+			b := data[iNdEx]
2819
+			iNdEx++
2820
+			wire |= (uint64(b) & 0x7F) << shift
2821
+			if b < 0x80 {
2822
+				break
2823
+			}
2824
+		}
2825
+		fieldNum := int32(wire >> 3)
2826
+		wireType := int(wire & 0x7)
2827
+		if wireType == 4 {
2828
+			return fmt.Errorf("proto: PublishLogsMessage: wiretype end group for non-group")
2829
+		}
2830
+		if fieldNum <= 0 {
2831
+			return fmt.Errorf("proto: PublishLogsMessage: illegal tag %d (wire type %d)", fieldNum, wire)
2832
+		}
2833
+		switch fieldNum {
2834
+		case 1:
2835
+			if wireType != 2 {
2836
+				return fmt.Errorf("proto: wrong wireType = %d for field SubscriptionID", wireType)
2837
+			}
2838
+			var stringLen uint64
2839
+			for shift := uint(0); ; shift += 7 {
2840
+				if shift >= 64 {
2841
+					return ErrIntOverflowLogbroker
2842
+				}
2843
+				if iNdEx >= l {
2844
+					return io.ErrUnexpectedEOF
2845
+				}
2846
+				b := data[iNdEx]
2847
+				iNdEx++
2848
+				stringLen |= (uint64(b) & 0x7F) << shift
2849
+				if b < 0x80 {
2850
+					break
2851
+				}
2852
+			}
2853
+			intStringLen := int(stringLen)
2854
+			if intStringLen < 0 {
2855
+				return ErrInvalidLengthLogbroker
2856
+			}
2857
+			postIndex := iNdEx + intStringLen
2858
+			if postIndex > l {
2859
+				return io.ErrUnexpectedEOF
2860
+			}
2861
+			m.SubscriptionID = string(data[iNdEx:postIndex])
2862
+			iNdEx = postIndex
2863
+		case 2:
2864
+			if wireType != 2 {
2865
+				return fmt.Errorf("proto: wrong wireType = %d for field Messages", wireType)
2866
+			}
2867
+			var msglen int
2868
+			for shift := uint(0); ; shift += 7 {
2869
+				if shift >= 64 {
2870
+					return ErrIntOverflowLogbroker
2871
+				}
2872
+				if iNdEx >= l {
2873
+					return io.ErrUnexpectedEOF
2874
+				}
2875
+				b := data[iNdEx]
2876
+				iNdEx++
2877
+				msglen |= (int(b) & 0x7F) << shift
2878
+				if b < 0x80 {
2879
+					break
2880
+				}
2881
+			}
2882
+			if msglen < 0 {
2883
+				return ErrInvalidLengthLogbroker
2884
+			}
2885
+			postIndex := iNdEx + msglen
2886
+			if postIndex > l {
2887
+				return io.ErrUnexpectedEOF
2888
+			}
2889
+			m.Messages = append(m.Messages, LogMessage{})
2890
+			if err := m.Messages[len(m.Messages)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
2891
+				return err
2892
+			}
2893
+			iNdEx = postIndex
2894
+		default:
2895
+			iNdEx = preIndex
2896
+			skippy, err := skipLogbroker(data[iNdEx:])
2897
+			if err != nil {
2898
+				return err
2899
+			}
2900
+			if skippy < 0 {
2901
+				return ErrInvalidLengthLogbroker
2902
+			}
2903
+			if (iNdEx + skippy) > l {
2904
+				return io.ErrUnexpectedEOF
2905
+			}
2906
+			iNdEx += skippy
2907
+		}
2908
+	}
2909
+
2910
+	if iNdEx > l {
2911
+		return io.ErrUnexpectedEOF
2912
+	}
2913
+	return nil
2914
+}
2915
+func (m *PublishLogsResponse) Unmarshal(data []byte) error {
2916
+	l := len(data)
2917
+	iNdEx := 0
2918
+	for iNdEx < l {
2919
+		preIndex := iNdEx
2920
+		var wire uint64
2921
+		for shift := uint(0); ; shift += 7 {
2922
+			if shift >= 64 {
2923
+				return ErrIntOverflowLogbroker
2924
+			}
2925
+			if iNdEx >= l {
2926
+				return io.ErrUnexpectedEOF
2927
+			}
2928
+			b := data[iNdEx]
2929
+			iNdEx++
2930
+			wire |= (uint64(b) & 0x7F) << shift
2931
+			if b < 0x80 {
2932
+				break
2933
+			}
2934
+		}
2935
+		fieldNum := int32(wire >> 3)
2936
+		wireType := int(wire & 0x7)
2937
+		if wireType == 4 {
2938
+			return fmt.Errorf("proto: PublishLogsResponse: wiretype end group for non-group")
2939
+		}
2940
+		if fieldNum <= 0 {
2941
+			return fmt.Errorf("proto: PublishLogsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
2942
+		}
2943
+		switch fieldNum {
2944
+		default:
2945
+			iNdEx = preIndex
2946
+			skippy, err := skipLogbroker(data[iNdEx:])
2947
+			if err != nil {
2948
+				return err
2949
+			}
2950
+			if skippy < 0 {
2951
+				return ErrInvalidLengthLogbroker
2952
+			}
2953
+			if (iNdEx + skippy) > l {
2954
+				return io.ErrUnexpectedEOF
2955
+			}
2956
+			iNdEx += skippy
2957
+		}
2958
+	}
2959
+
2960
+	if iNdEx > l {
2961
+		return io.ErrUnexpectedEOF
2962
+	}
2963
+	return nil
2964
+}
2965
+func skipLogbroker(data []byte) (n int, err error) {
2966
+	l := len(data)
2967
+	iNdEx := 0
2968
+	for iNdEx < l {
2969
+		var wire uint64
2970
+		for shift := uint(0); ; shift += 7 {
2971
+			if shift >= 64 {
2972
+				return 0, ErrIntOverflowLogbroker
2973
+			}
2974
+			if iNdEx >= l {
2975
+				return 0, io.ErrUnexpectedEOF
2976
+			}
2977
+			b := data[iNdEx]
2978
+			iNdEx++
2979
+			wire |= (uint64(b) & 0x7F) << shift
2980
+			if b < 0x80 {
2981
+				break
2982
+			}
2983
+		}
2984
+		wireType := int(wire & 0x7)
2985
+		switch wireType {
2986
+		case 0:
2987
+			for shift := uint(0); ; shift += 7 {
2988
+				if shift >= 64 {
2989
+					return 0, ErrIntOverflowLogbroker
2990
+				}
2991
+				if iNdEx >= l {
2992
+					return 0, io.ErrUnexpectedEOF
2993
+				}
2994
+				iNdEx++
2995
+				if data[iNdEx-1] < 0x80 {
2996
+					break
2997
+				}
2998
+			}
2999
+			return iNdEx, nil
3000
+		case 1:
3001
+			iNdEx += 8
3002
+			return iNdEx, nil
3003
+		case 2:
3004
+			var length int
3005
+			for shift := uint(0); ; shift += 7 {
3006
+				if shift >= 64 {
3007
+					return 0, ErrIntOverflowLogbroker
3008
+				}
3009
+				if iNdEx >= l {
3010
+					return 0, io.ErrUnexpectedEOF
3011
+				}
3012
+				b := data[iNdEx]
3013
+				iNdEx++
3014
+				length |= (int(b) & 0x7F) << shift
3015
+				if b < 0x80 {
3016
+					break
3017
+				}
3018
+			}
3019
+			iNdEx += length
3020
+			if length < 0 {
3021
+				return 0, ErrInvalidLengthLogbroker
3022
+			}
3023
+			return iNdEx, nil
3024
+		case 3:
3025
+			for {
3026
+				var innerWire uint64
3027
+				var start int = iNdEx
3028
+				for shift := uint(0); ; shift += 7 {
3029
+					if shift >= 64 {
3030
+						return 0, ErrIntOverflowLogbroker
3031
+					}
3032
+					if iNdEx >= l {
3033
+						return 0, io.ErrUnexpectedEOF
3034
+					}
3035
+					b := data[iNdEx]
3036
+					iNdEx++
3037
+					innerWire |= (uint64(b) & 0x7F) << shift
3038
+					if b < 0x80 {
3039
+						break
3040
+					}
3041
+				}
3042
+				innerWireType := int(innerWire & 0x7)
3043
+				if innerWireType == 4 {
3044
+					break
3045
+				}
3046
+				next, err := skipLogbroker(data[start:])
3047
+				if err != nil {
3048
+					return 0, err
3049
+				}
3050
+				iNdEx = start + next
3051
+			}
3052
+			return iNdEx, nil
3053
+		case 4:
3054
+			return iNdEx, nil
3055
+		case 5:
3056
+			iNdEx += 4
3057
+			return iNdEx, nil
3058
+		default:
3059
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
3060
+		}
3061
+	}
3062
+	panic("unreachable")
3063
+}
3064
+
3065
+var (
3066
+	ErrInvalidLengthLogbroker = fmt.Errorf("proto: negative length found during unmarshaling")
3067
+	ErrIntOverflowLogbroker   = fmt.Errorf("proto: integer overflow")
3068
+)
3069
+
3070
+func init() { proto.RegisterFile("logbroker.proto", fileDescriptorLogbroker) }
3071
+
3072
+var fileDescriptorLogbroker = []byte{
3073
+	// 872 bytes of a gzipped FileDescriptorProto
3074
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x95, 0x4f, 0x8f, 0xdb, 0x44,
3075
+	0x18, 0xc6, 0x33, 0xce, 0x36, 0x7f, 0xde, 0x74, 0xff, 0x74, 0xb2, 0x5d, 0x85, 0xa8, 0x75, 0x22,
3076
+	0x57, 0x2a, 0xd1, 0xaa, 0x64, 0x61, 0x2b, 0xc4, 0xa1, 0x12, 0x82, 0x90, 0x0a, 0x45, 0xa4, 0xbb,
3077
+	0x68, 0x92, 0x15, 0xdc, 0x56, 0x4e, 0x3c, 0x18, 0x2b, 0x8e, 0x27, 0x78, 0x9c, 0x86, 0x03, 0x07,
3078
+	0x0e, 0x45, 0x42, 0x3d, 0x70, 0x41, 0x48, 0x70, 0xe8, 0x89, 0xde, 0x90, 0x38, 0x70, 0xe4, 0x03,
3079
+	0xa0, 0x15, 0x27, 0x0e, 0x1c, 0x38, 0x45, 0xac, 0x3f, 0x00, 0xe2, 0x23, 0x20, 0xcf, 0x4c, 0x1c,
3080
+	0x2f, 0x71, 0x58, 0xb4, 0xbd, 0x24, 0x33, 0x9e, 0xe7, 0xf5, 0xfb, 0x9b, 0x67, 0x9e, 0x91, 0x61,
3081
+	0xdb, 0x65, 0xf6, 0xc0, 0x67, 0x23, 0xea, 0x37, 0x27, 0x3e, 0x0b, 0x18, 0xc6, 0x16, 0x1b, 0x46,
3082
+	0x33, 0x3e, 0x33, 0xfd, 0xf1, 0xc8, 0x09, 0x9a, 0x8f, 0x5f, 0xab, 0xee, 0xda, 0xcc, 0x66, 0x62,
3083
+	0xf9, 0x20, 0x1a, 0x49, 0x65, 0xf5, 0xa5, 0xc0, 0x19, 0x53, 0x1e, 0x98, 0xe3, 0xc9, 0x41, 0x3c,
3084
+	0x52, 0x4b, 0xe5, 0x89, 0x3b, 0xb5, 0x1d, 0xef, 0x40, 0xfe, 0xc9, 0x87, 0xc6, 0x4f, 0x08, 0xf6,
3085
+	0xba, 0xcc, 0xee, 0x4d, 0x07, 0x7c, 0xe8, 0x3b, 0x93, 0xc0, 0x61, 0xde, 0xb1, 0xf8, 0xe5, 0xf8,
3086
+	0x0d, 0xc8, 0xf3, 0xc0, 0xa7, 0xe6, 0x98, 0x57, 0x50, 0x3d, 0xdb, 0xd8, 0x3a, 0xbc, 0xdd, 0x5c,
3087
+	0xc5, 0x68, 0x46, 0xc5, 0x42, 0x45, 0x16, 0x6a, 0xbc, 0x07, 0xb9, 0x8f, 0x98, 0xeb, 0xb2, 0x59,
3088
+	0x45, 0xab, 0xa3, 0x46, 0x81, 0xa8, 0x19, 0xc6, 0xb0, 0x11, 0x98, 0x8e, 0x5b, 0xc9, 0xd6, 0x51,
3089
+	0x23, 0x4b, 0xc4, 0x18, 0xdf, 0x87, 0x6b, 0xdc, 0xf1, 0x86, 0xb4, 0xb2, 0x51, 0x47, 0x8d, 0x52,
3090
+	0x7a, 0x8b, 0xfe, 0x62, 0x23, 0x44, 0x6a, 0x8d, 0xaf, 0x10, 0x94, 0xa2, 0xbe, 0xd4, 0xa5, 0xc3,
3091
+	0x80, 0xf9, 0xf8, 0x00, 0x4a, 0x9c, 0xfa, 0x8f, 0x9d, 0x21, 0x3d, 0x75, 0x2c, 0x49, 0x5b, 0x6c,
3092
+	0x6d, 0x85, 0xf3, 0x1a, 0xf4, 0xe4, 0xe3, 0x4e, 0x9b, 0x13, 0x50, 0x92, 0x8e, 0xc5, 0xf1, 0x5d,
3093
+	0x28, 0x78, 0xcc, 0x92, 0x6a, 0x4d, 0xa8, 0x4b, 0xe1, 0xbc, 0x96, 0x3f, 0x62, 0x96, 0x90, 0xe6,
3094
+	0xa3, 0x45, 0xa5, 0x0b, 0x4c, 0x3e, 0x12, 0xba, 0xec, 0x52, 0xd7, 0x37, 0xf9, 0x48, 0xe8, 0xa2,
3095
+	0xc5, 0x8e, 0xc5, 0x8d, 0x27, 0x08, 0xa0, 0xcb, 0xec, 0x77, 0x98, 0x17, 0xd0, 0x4f, 0x03, 0x7c,
3096
+	0x0f, 0x60, 0xc9, 0x53, 0x41, 0x75, 0xd4, 0x28, 0xb6, 0x36, 0xc3, 0x79, 0xad, 0x18, 0xe3, 0x90,
3097
+	0x62, 0x4c, 0x83, 0xef, 0x40, 0x5e, 0xc1, 0x08, 0xbf, 0x8a, 0x2d, 0x08, 0xe7, 0xb5, 0x9c, 0x64,
3098
+	0x21, 0x39, 0x89, 0x12, 0x89, 0x14, 0x89, 0xb0, 0x4f, 0x89, 0x24, 0x08, 0xc9, 0x49, 0x0e, 0xe3,
3099
+	0x77, 0x89, 0xf1, 0x88, 0x72, 0x6e, 0xda, 0x14, 0xbf, 0x09, 0xf9, 0xa1, 0x24, 0x12, 0x0c, 0xa5,
3100
+	0x43, 0x7d, 0xcd, 0x01, 0x2a, 0xee, 0xd6, 0xc6, 0xd9, 0xbc, 0x96, 0x21, 0x8b, 0x22, 0xfc, 0x00,
3101
+	0x8a, 0x71, 0x86, 0x04, 0xda, 0xa5, 0xe7, 0xb3, 0xd4, 0xe3, 0xd7, 0x21, 0x27, 0xf3, 0x20, 0x78,
3102
+	0x2f, 0x0d, 0x8f, 0x12, 0x47, 0x19, 0xb1, 0xcc, 0xc0, 0x14, 0x71, 0xb8, 0x4e, 0xc4, 0xd8, 0xf8,
3103
+	0x0e, 0xc1, 0xae, 0x0a, 0xe8, 0x80, 0x76, 0x99, 0xcd, 0x09, 0xfd, 0x64, 0x4a, 0x79, 0x04, 0x58,
3104
+	0xe0, 0x2a, 0x03, 0x6a, 0x87, 0xb5, 0x75, 0x5d, 0x94, 0x8c, 0xc4, 0x05, 0xb8, 0x0d, 0x79, 0x26,
3105
+	0x93, 0xae, 0xf6, 0xb6, 0xbf, 0xae, 0x76, 0xf5, 0x6e, 0x90, 0x45, 0xa9, 0xf1, 0xe1, 0xbf, 0xd0,
3106
+	0x16, 0xde, 0xbf, 0x05, 0x85, 0xb1, 0x1c, 0xca, 0x3c, 0xae, 0x37, 0x5f, 0x55, 0x28, 0xf3, 0xe3,
3107
+	0x2a, 0xe3, 0x16, 0x54, 0xbb, 0x0e, 0x0f, 0xa8, 0x97, 0xec, 0xbf, 0xd8, 0xba, 0xf1, 0x0b, 0x82,
3108
+	0x72, 0x72, 0x61, 0xd1, 0x77, 0x0f, 0xb4, 0x38, 0x72, 0xb9, 0x70, 0x5e, 0xd3, 0x3a, 0x6d, 0xa2,
3109
+	0x39, 0xd6, 0x05, 0xab, 0xb4, 0x17, 0xb0, 0x2a, 0x7b, 0x65, 0xab, 0xf0, 0x2e, 0x5c, 0x1b, 0xba,
3110
+	0x8c, 0xcb, 0xab, 0x5e, 0x20, 0x72, 0x62, 0x7c, 0x8d, 0x00, 0xbf, 0x3f, 0x1d, 0xb8, 0x0e, 0xff,
3111
+	0x38, 0xe9, 0xdf, 0x03, 0xd8, 0xe6, 0x89, 0x97, 0x2d, 0xef, 0x11, 0x0e, 0xe7, 0xb5, 0xad, 0x64,
3112
+	0x9f, 0x4e, 0x9b, 0x6c, 0x25, 0xa5, 0x1d, 0xeb, 0x82, 0xf9, 0xda, 0x95, 0xcc, 0xbf, 0x09, 0xe5,
3113
+	0x04, 0x14, 0xa1, 0x7c, 0xc2, 0x3c, 0x4e, 0xf7, 0x9f, 0x23, 0x28, 0xc6, 0x99, 0xc5, 0xf7, 0x00,
3114
+	0x77, 0x8f, 0xdf, 0x3d, 0xed, 0xf5, 0xc9, 0xc3, 0xb7, 0x1f, 0x9d, 0x9e, 0x1c, 0xbd, 0x77, 0x74,
3115
+	0xfc, 0xc1, 0xd1, 0x4e, 0xa6, 0xba, 0xfb, 0xf4, 0x59, 0x7d, 0x27, 0x96, 0x9d, 0x78, 0x23, 0x8f,
3116
+	0xcd, 0x3c, 0xbc, 0x0f, 0x37, 0x12, 0xea, 0x5e, 0xbf, 0x7d, 0x7c, 0xd2, 0xdf, 0x41, 0xd5, 0xf2,
3117
+	0xd3, 0x67, 0xf5, 0xed, 0x58, 0xdc, 0x0b, 0x2c, 0x36, 0x0d, 0x56, 0xb5, 0x0f, 0x09, 0xd9, 0xd1,
3118
+	0x56, 0xb5, 0xd4, 0xf7, 0xab, 0x37, 0xbe, 0xfc, 0x5e, 0xcf, 0xfc, 0xfc, 0x5c, 0x5f, 0x82, 0x1d,
3119
+	0x3e, 0x41, 0xb0, 0x11, 0x71, 0xe3, 0xcf, 0x60, 0xf3, 0x42, 0x3a, 0x71, 0x23, 0xcd, 0x87, 0xb4,
3120
+	0xbb, 0x55, 0xbd, 0x5c, 0xa9, 0xbc, 0x33, 0x6e, 0xfe, 0xfa, 0xe3, 0x5f, 0xdf, 0x6a, 0xdb, 0xb0,
3121
+	0x29, 0x94, 0xaf, 0x8c, 0x4d, 0xcf, 0xb4, 0xa9, 0xff, 0x2a, 0x3a, 0xfc, 0x41, 0x13, 0x6e, 0xb5,
3122
+	0xc4, 0x97, 0x0c, 0x7f, 0x83, 0xa0, 0x9c, 0x12, 0x68, 0xdc, 0x4c, 0x3d, 0x9a, 0xb5, 0xc9, 0xaf,
3123
+	0xbe, 0xfc, 0x1f, 0x60, 0xc9, 0xab, 0x60, 0xdc, 0x11, 0x5c, 0xb7, 0xe1, 0xba, 0xe4, 0x9a, 0x31,
3124
+	0x7f, 0x44, 0xfd, 0x15, 0x4a, 0xfc, 0x05, 0x82, 0x52, 0xe2, 0xac, 0xf1, 0xdd, 0xb4, 0xf7, 0xaf,
3125
+	0x26, 0x34, 0x9d, 0x23, 0x25, 0x34, 0xff, 0x8b, 0xa3, 0x81, 0x5a, 0xb7, 0xce, 0xce, 0xf5, 0xcc,
3126
+	0x1f, 0xe7, 0x7a, 0xe6, 0xef, 0x73, 0x1d, 0x7d, 0x1e, 0xea, 0xe8, 0x2c, 0xd4, 0xd1, 0x6f, 0xa1,
3127
+	0x8e, 0xfe, 0x0c, 0x75, 0x34, 0xc8, 0x89, 0xcf, 0xf5, 0xfd, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff,
3128
+	0x8b, 0xff, 0xc0, 0x45, 0x1b, 0x08, 0x00, 0x00,
3129
+}
0 3130
new file mode 100644
... ...
@@ -0,0 +1,170 @@
0
+syntax = "proto3";
1
+
2
+package docker.swarmkit.v1;
3
+
4
+import "gogoproto/gogo.proto";
5
+import "timestamp/timestamp.proto"; // TODO(stevvooe): use our own until we fix gogoproto/deepcopy
6
+import "plugin/plugin.proto";
7
+
8
+// LogStream defines the stream from which the log message came.
9
+enum LogStream {
10
+	option (gogoproto.goproto_enum_prefix) = false;
11
+	option (gogoproto.enum_customname) = "LogStream";
12
+
13
+	LOG_STREAM_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "LogStreamUnknown"];
14
+	LOG_STREAM_STDOUT = 1 [(gogoproto.enumvalue_customname) = "LogStreamStdout"];
15
+	LOG_STREAM_STDERR = 2 [(gogoproto.enumvalue_customname) = "LogStreamStderr"];
16
+}
17
+
18
+message LogSubscriptionOptions {
19
+	// Streams defines which log streams should be sent from the task source.
20
+	// Empty means send all the messages.
21
+	repeated LogStream streams = 1;
22
+
23
+	// Follow instructs the publisher to continue sending log messages as they
24
+	// are produced, after satisfying the initial query.
25
+	bool follow = 2;
26
+
27
+	// Tail defines how many messages relative to the log stream to send when
28
+	// starting the stream.
29
+	//
30
+	// Positive values will skip that number of messages from the start of the
31
+	// stream before publishing.
32
+	//
33
+	// Negative values will specify messages relative to the end of the stream,
34
+	// offset by one. We can say that the last (-n-1) lines are returned when n
35
+	// < 0. As reference, -1 would mean send no log lines (typically used with
36
+	// follow), -2 would return the last log line, -11 would return the last 10
37
+	// and so on.
38
+	//
39
+	// The default value of zero will return all logs.
40
+	//
41
+	// Note that this is very different from the Docker API.
42
+	int64 tail = 3;
43
+
44
+	// Since indicates that only log messages produced after this timestamp
45
+	// should be sent.
46
+	Timestamp since = 4;
47
+}
48
+
49
+// LogSelector will match logs from ANY of the defined parameters.
50
+//
51
+// For the best effect, the client should use the least specific parameter
52
+// possible. For example, if they want to listen to all the tasks of a service,
53
+// they should use the service id, rather than specifying the individual tasks.
54
+message LogSelector {
55
+	repeated string service_ids = 1 [(gogoproto.customname) = "ServiceIDs"];
56
+	repeated string node_ids = 2 [(gogoproto.customname) = "NodeIDs"];
57
+	repeated string task_ids = 3 [(gogoproto.customname) = "TaskIDs"];
58
+}
59
+
60
+// LogContext marks the context from which a log message was generated.
61
+message LogContext {
62
+	string service_id = 1 [(gogoproto.customname) = "ServiceID"];
63
+	string node_id = 2 [(gogoproto.customname) = "NodeID"];
64
+	string task_id = 3 [(gogoproto.customname) = "TaskID"];
65
+}
66
+
67
+// LogMessage
68
+message LogMessage {
69
+	// Context identifies the source of the log message.
70
+	LogContext context = 1 [(gogoproto.nullable) = false];
71
+
72
+	// Timestamp is the time at which the message was generated.
73
+	Timestamp timestamp = 2;
74
+
75
+	// Stream identifies the stream of the log message, stdout or stderr.
76
+	LogStream stream = 3;
77
+
78
+	// Data is the raw log message, as generated by the application.
79
+	bytes data = 4;
80
+}
81
+
82
+// Logs defines the methods for retrieving task logs messages from a cluster.
83
+service Logs {
84
+	// SubscribeLogs starts a subscription with the specified selector and options.
85
+	//
86
+	// The subscription will be distributed to relevant nodes and messages will
87
+	// be collected and sent via the returned stream.
88
+	//
89
+	// The subscription will end with an EOF.
90
+	rpc SubscribeLogs(SubscribeLogsRequest) returns (stream SubscribeLogsMessage) {
91
+		option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
92
+	}
93
+}
94
+
95
+message SubscribeLogsRequest {
96
+	// LogSelector describes the logs to which the subscriber is
97
+	LogSelector selector = 1;
98
+
99
+	LogSubscriptionOptions options = 2;
100
+}
101
+
102
+message SubscribeLogsMessage {
103
+	repeated LogMessage messages = 1 [(gogoproto.nullable) = false];
104
+}
105
+
106
+// LogBroker defines the API used by the worker to send task logs back to a
107
+// manager. A client listens for subscriptions then optimistically retrieves
108
+// logs satisfying said subscriptions, calling PublishLogs for results that are
109
+// relevant.
110
+//
111
+// The structure of ListenSubscriptions is similar to the Dispatcher API but
112
+// decoupled to allow log distribution to work outside of the regular task
113
+// flow.
114
+service LogBroker {
115
+	// ListenSubscriptions starts a subscription stream for the node. For each
116
+	// message received, the node should attempt to satisfy the subscription.
117
+	//
118
+	// Log messages that match the provided subscription should be sent via
119
+	// PublishLogs.
120
+	rpc ListenSubscriptions(ListenSubscriptionsRequest) returns (stream SubscriptionMessage) {
121
+		option (docker.protobuf.plugin.tls_authorization) = {
122
+			roles: "swarm-worker"
123
+			roles: "swarm-manager"
124
+		};
125
+	}
126
+
127
+	// PublishLogs receives sets of log messages destined for a single
128
+	// subscription identifier.
129
+	rpc PublishLogs(stream PublishLogsMessage) returns (PublishLogsResponse) {
130
+		option (docker.protobuf.plugin.tls_authorization) = {
131
+			roles: "swarm-worker"
132
+			roles: "swarm-manager"
133
+		};
134
+	}
135
+}
136
+
137
+// ListenSubscriptionsRequest is a placeholder to begin listening for
138
+// subscriptions.
139
+message ListenSubscriptionsRequest { }
140
+
141
+// SubscriptionMessage instructs the listener to start publishing messages for
142
+// the stream or end a subscription.
143
+//
144
+// If Options.Follow == false, the worker should end the subscription on its own.
145
+message SubscriptionMessage {
146
+	// ID identifies the subscription.
147
+	string id = 1 [(gogoproto.customname) = "ID"];
148
+
149
+	// Selector defines which sources should be sent for the subscription.
150
+	LogSelector selector = 2;
151
+
152
+	// Options specify how the subscription should be satisfied.
153
+	LogSubscriptionOptions options = 3;
154
+
155
+	// Close will be true if the node should shutdown the subscription with the
156
+	// provided identifier.
157
+	bool close = 4;
158
+}
159
+
160
+message PublishLogsMessage {
161
+	// SubscriptionID identifies which subscription the set of messages should
162
+	// be sent to. We can think of this as a "mail box" for the subscription.
163
+	string subscription_id = 1 [(gogoproto.customname) = "SubscriptionID"];
164
+
165
+	// Messages is the log message for publishing.
166
+	repeated LogMessage messages = 2 [(gogoproto.nullable) = false];
167
+}
168
+
169
+message PublishLogsResponse { }
... ...
@@ -16,6 +16,7 @@
16 16
 		raft.proto
17 17
 		health.proto
18 18
 		resource.proto
19
+		logbroker.proto
19 20
 
20 21
 	It has these top-level messages:
21 22
 		Version
... ...
@@ -168,6 +169,16 @@
168 168
 		AttachNetworkResponse
169 169
 		DetachNetworkRequest
170 170
 		DetachNetworkResponse
171
+		LogSubscriptionOptions
172
+		LogSelector
173
+		LogContext
174
+		LogMessage
175
+		SubscribeLogsRequest
176
+		SubscribeLogsMessage
177
+		ListenSubscriptionsRequest
178
+		SubscriptionMessage
179
+		PublishLogsMessage
180
+		PublishLogsResponse
171 181
 */
172 182
 package api
173 183
 
... ...
@@ -145,36 +145,29 @@ func (s *Server) GetNetwork(ctx context.Context, request *api.GetNetworkRequest)
145 145
 // - Returns `NotFound` if the Network is not found.
146 146
 // - Returns an error if the deletion fails.
147 147
 func (s *Server) RemoveNetwork(ctx context.Context, request *api.RemoveNetworkRequest) (*api.RemoveNetworkResponse, error) {
148
-	var (
149
-		services []*api.Service
150
-		err      error
151
-	)
152
-
153 148
 	if request.NetworkID == "" {
154 149
 		return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
155 150
 	}
156 151
 
157
-	s.store.View(func(tx store.ReadTx) {
158
-		services, err = store.FindServices(tx, store.All)
159
-	})
160
-	if err != nil {
161
-		return nil, grpc.Errorf(codes.Internal, "could not find services using network %s", request.NetworkID)
162
-	}
152
+	err := s.store.Update(func(tx store.Tx) error {
153
+		services, err := store.FindServices(tx, store.ByReferencedNetworkID(request.NetworkID))
154
+		if err != nil {
155
+			return grpc.Errorf(codes.Internal, "could not find services using network %s: %v", request.NetworkID, err)
156
+		}
163 157
 
164
-	for _, s := range services {
165
-		specNetworks := s.Spec.Task.Networks
166
-		if len(specNetworks) == 0 {
167
-			specNetworks = s.Spec.Networks
158
+		if len(services) != 0 {
159
+			return grpc.Errorf(codes.FailedPrecondition, "network %s is in use by service %s", request.NetworkID, services[0].ID)
168 160
 		}
169 161
 
170
-		for _, na := range specNetworks {
171
-			if na.Target == request.NetworkID {
172
-				return nil, grpc.Errorf(codes.FailedPrecondition, "network %s is in use", request.NetworkID)
173
-			}
162
+		tasks, err := store.FindTasks(tx, store.ByReferencedNetworkID(request.NetworkID))
163
+		if err != nil {
164
+			return grpc.Errorf(codes.Internal, "could not find tasks using network %s: %v", request.NetworkID, err)
165
+		}
166
+
167
+		if len(tasks) != 0 {
168
+			return grpc.Errorf(codes.FailedPrecondition, "network %s is in use by task %s", request.NetworkID, tasks[0].ID)
174 169
 		}
175
-	}
176 170
 
177
-	err = s.store.Update(func(tx store.Tx) error {
178 171
 		nw := store.GetNetwork(tx, request.NetworkID)
179 172
 		if _, ok := nw.Spec.Annotations.Labels["com.docker.swarm.internal"]; ok {
180 173
 			networkDescription := nw.ID
... ...
@@ -2,6 +2,7 @@ package controlapi
2 2
 
3 3
 import (
4 4
 	"regexp"
5
+	"strings"
5 6
 
6 7
 	"github.com/Sirupsen/logrus"
7 8
 	"github.com/docker/distribution/digest"
... ...
@@ -191,6 +192,7 @@ func (s *Server) CreateSecret(ctx context.Context, request *api.CreateSecretRequ
191 191
 // RemoveSecret removes the secret referenced by `RemoveSecretRequest.ID`.
192 192
 // - Returns `InvalidArgument` if `RemoveSecretRequest.ID` is empty.
193 193
 // - Returns `NotFound` if the a secret named `RemoveSecretRequest.ID` is not found.
194
+// - Returns `SecretInUse` if the secret is currently in use
194 195
 // - Returns an error if the deletion fails.
195 196
 func (s *Server) RemoveSecret(ctx context.Context, request *api.RemoveSecretRequest) (*api.RemoveSecretResponse, error) {
196 197
 	if request.SecretID == "" {
... ...
@@ -198,6 +200,34 @@ func (s *Server) RemoveSecret(ctx context.Context, request *api.RemoveSecretRequ
198 198
 	}
199 199
 
200 200
 	err := s.store.Update(func(tx store.Tx) error {
201
+		// Check if the secret exists
202
+		secret := store.GetSecret(tx, request.SecretID)
203
+		if secret == nil {
204
+			return grpc.Errorf(codes.NotFound, "could not find secret %s", request.SecretID)
205
+		}
206
+
207
+		// Check if any services currently reference this secret, return error if so
208
+		services, err := store.FindServices(tx, store.ByReferencedSecretID(request.SecretID))
209
+		if err != nil {
210
+			return grpc.Errorf(codes.Internal, "could not find services using secret %s: %v", request.SecretID, err)
211
+		}
212
+
213
+		if len(services) != 0 {
214
+			serviceNames := make([]string, 0, len(services))
215
+			for _, service := range services {
216
+				serviceNames = append(serviceNames, service.Spec.Annotations.Name)
217
+			}
218
+
219
+			secretName := secret.Spec.Annotations.Name
220
+			serviceNameStr := strings.Join(serviceNames, ", ")
221
+			serviceStr := "services"
222
+			if len(serviceNames) == 1 {
223
+				serviceStr = "service"
224
+			}
225
+
226
+			return grpc.Errorf(codes.InvalidArgument, "secret '%s' is in use by the following %s: %v", secretName, serviceStr, serviceNameStr)
227
+		}
228
+
201 229
 		return store.DeleteSecret(tx, request.SecretID)
202 230
 	})
203 231
 	switch err {
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"reflect"
7 7
 	"regexp"
8 8
 	"strconv"
9
+	"strings"
9 10
 
10 11
 	"github.com/docker/distribution/reference"
11 12
 	"github.com/docker/swarmkit/api"
... ...
@@ -208,6 +209,47 @@ func validateEndpointSpec(epSpec *api.EndpointSpec) error {
208 208
 	return nil
209 209
 }
210 210
 
211
+// validateSecretRefsSpec finds if the secrets passed in spec are valid and have no
212
+// conflicting targets.
213
+func validateSecretRefsSpec(spec *api.ServiceSpec) error {
214
+	container := spec.Task.GetContainer()
215
+	if container == nil {
216
+		return nil
217
+	}
218
+
219
+	// Keep a map to track all the targets that will be exposed
220
+	// The string returned is only used for logging. It could as well be struct{}{}
221
+	existingTargets := make(map[string]string)
222
+	for _, secretRef := range container.Secrets {
223
+		// SecretID and SecretName are mandatory, we have invalid references without them
224
+		if secretRef.SecretID == "" || secretRef.SecretName == "" {
225
+			return grpc.Errorf(codes.InvalidArgument, "malformed secret reference")
226
+		}
227
+
228
+		// Every secret referece requires a Target
229
+		if secretRef.GetTarget() == nil {
230
+			return grpc.Errorf(codes.InvalidArgument, "malformed secret reference, no target provided")
231
+		}
232
+
233
+		// If this is a file target, we will ensure filename uniqueness
234
+		if secretRef.GetFile() != nil {
235
+			fileName := secretRef.GetFile().Name
236
+			// Validate the file name
237
+			if fileName == "" || fileName != filepath.Base(filepath.Clean(fileName)) {
238
+				return grpc.Errorf(codes.InvalidArgument, "malformed file secret reference, invalid target file name provided")
239
+			}
240
+
241
+			// If this target is already in use, we have conflicting targets
242
+			if prevSecretName, ok := existingTargets[fileName]; ok {
243
+				return grpc.Errorf(codes.InvalidArgument, "secret references '%s' and '%s' have a conflicting target: '%s'", prevSecretName, secretRef.SecretName, fileName)
244
+			}
245
+
246
+			existingTargets[fileName] = secretRef.SecretName
247
+		}
248
+	}
249
+
250
+	return nil
251
+}
211 252
 func (s *Server) validateNetworks(networks []*api.NetworkAttachmentConfig) error {
212 253
 	for _, na := range networks {
213 254
 		var network *api.Network
... ...
@@ -242,6 +284,11 @@ func validateServiceSpec(spec *api.ServiceSpec) error {
242 242
 	if err := validateEndpointSpec(spec.Endpoint); err != nil {
243 243
 		return err
244 244
 	}
245
+	// Check to see if the Secret Reference portion of the spec is valid
246
+	if err := validateSecretRefsSpec(spec); err != nil {
247
+		return err
248
+	}
249
+
245 250
 	return nil
246 251
 }
247 252
 
... ...
@@ -305,42 +352,30 @@ func (s *Server) checkPortConflicts(spec *api.ServiceSpec, serviceID string) err
305 305
 	return nil
306 306
 }
307 307
 
308
-// checkSecretValidity finds if the secrets passed in spec have any conflicting targets.
309
-func (s *Server) checkSecretValidity(spec *api.ServiceSpec) error {
308
+// checkSecretExistence finds if the secret exists
309
+func (s *Server) checkSecretExistence(tx store.Tx, spec *api.ServiceSpec) error {
310 310
 	container := spec.Task.GetContainer()
311 311
 	if container == nil {
312 312
 		return nil
313 313
 	}
314 314
 
315
-	// Keep a map to track all the targets that will be exposed
316
-	// The string returned is only used for logging. It could as well be struct{}{}
317
-	existingTargets := make(map[string]string)
315
+	var failedSecrets []string
318 316
 	for _, secretRef := range container.Secrets {
319
-		// SecretID and SecretName are mandatory, we have invalid references without them
320
-		if secretRef.SecretID == "" || secretRef.SecretName == "" {
321
-			return grpc.Errorf(codes.InvalidArgument, "malformed secret reference")
317
+		secret := store.GetSecret(tx, secretRef.SecretID)
318
+		// Check to see if the secret exists and secretRef.SecretName matches the actual secretName
319
+		if secret == nil || secret.Spec.Annotations.Name != secretRef.SecretName {
320
+			failedSecrets = append(failedSecrets, secretRef.SecretName)
322 321
 		}
322
+	}
323 323
 
324
-		// Every secret referece requires a Target
325
-		if secretRef.GetTarget() == nil {
326
-			return grpc.Errorf(codes.InvalidArgument, "malformed secret reference, no target provided")
324
+	if len(failedSecrets) > 0 {
325
+		secretStr := "secrets"
326
+		if len(failedSecrets) == 1 {
327
+			secretStr = "secret"
327 328
 		}
328 329
 
329
-		// If this is a file target, we will ensure filename uniqueness
330
-		if secretRef.GetFile() != nil {
331
-			fileName := secretRef.GetFile().Name
332
-			// Validate the file name
333
-			if fileName == "" || fileName != filepath.Base(filepath.Clean(fileName)) {
334
-				return grpc.Errorf(codes.InvalidArgument, "malformed file secret reference, invalid target file name provided")
335
-			}
330
+		return grpc.Errorf(codes.InvalidArgument, "%s not found: %v", secretStr, strings.Join(failedSecrets, ", "))
336 331
 
337
-			// If this target is already in use, we have conflicting targets
338
-			if prevSecretName, ok := existingTargets[fileName]; ok {
339
-				return grpc.Errorf(codes.InvalidArgument, "secret references '%s' and '%s' have a conflicting target: '%s'", prevSecretName, secretRef.SecretName, fileName)
340
-			}
341
-
342
-			existingTargets[fileName] = secretRef.SecretName
343
-		}
344 332
 	}
345 333
 
346 334
 	return nil
... ...
@@ -364,10 +399,6 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe
364 364
 		return nil, err
365 365
 	}
366 366
 
367
-	if err := s.checkSecretValidity(request.Spec); err != nil {
368
-		return nil, err
369
-	}
370
-
371 367
 	// TODO(aluzzardi): Consider using `Name` as a primary key to handle
372 368
 	// duplicate creations. See #65
373 369
 	service := &api.Service{
... ...
@@ -376,6 +407,13 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe
376 376
 	}
377 377
 
378 378
 	err := s.store.Update(func(tx store.Tx) error {
379
+		// Check to see if all the secrets being added exist as objects
380
+		// in our datastore
381
+		err := s.checkSecretExistence(tx, request.Spec)
382
+		if err != nil {
383
+			return err
384
+		}
385
+
379 386
 		return store.CreateService(tx, service)
380 387
 	})
381 388
 	if err != nil {
... ...
@@ -435,10 +473,6 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
435 435
 		}
436 436
 	}
437 437
 
438
-	if err := s.checkSecretValidity(request.Spec); err != nil {
439
-		return nil, err
440
-	}
441
-
442 438
 	err := s.store.Update(func(tx store.Tx) error {
443 439
 		service = store.GetService(tx, request.ServiceID)
444 440
 		if service == nil {
... ...
@@ -459,6 +493,13 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
459 459
 			return errNetworkUpdateNotSupported
460 460
 		}
461 461
 
462
+		// Check to see if all the secrets being added exist as objects
463
+		// in our datastore
464
+		err := s.checkSecretExistence(tx, request.Spec)
465
+		if err != nil {
466
+			return err
467
+		}
468
+
462 469
 		// orchestrator is designed to be stateless, so it should not deal
463 470
 		// with service mode change (comparing current config with previous config).
464 471
 		// proper way to change service mode is to delete and re-add.
... ...
@@ -19,9 +19,9 @@ import (
19 19
 	"github.com/docker/swarmkit/log"
20 20
 	"github.com/docker/swarmkit/manager/state"
21 21
 	"github.com/docker/swarmkit/manager/state/store"
22
-	"github.com/docker/swarmkit/manager/state/watch"
23 22
 	"github.com/docker/swarmkit/protobuf/ptypes"
24 23
 	"github.com/docker/swarmkit/remotes"
24
+	"github.com/docker/swarmkit/watch"
25 25
 	"github.com/pkg/errors"
26 26
 	"golang.org/x/net/context"
27 27
 )
28 28
new file mode 100644
... ...
@@ -0,0 +1,273 @@
0
+package logbroker
1
+
2
+import (
3
+	"errors"
4
+	"io"
5
+	"sync"
6
+
7
+	"google.golang.org/grpc"
8
+	"google.golang.org/grpc/codes"
9
+
10
+	"github.com/Sirupsen/logrus"
11
+	"github.com/docker/go-events"
12
+	"github.com/docker/swarmkit/api"
13
+	"github.com/docker/swarmkit/ca"
14
+	"github.com/docker/swarmkit/identity"
15
+	"github.com/docker/swarmkit/log"
16
+	"github.com/docker/swarmkit/watch"
17
+	"golang.org/x/net/context"
18
+)
19
+
20
+var (
21
+	errAlreadyRunning = errors.New("broker is already running")
22
+	errNotRunning     = errors.New("broker is not running")
23
+)
24
+
25
+// LogBroker coordinates log subscriptions to services and tasks. Çlients can
26
+// publish and subscribe to logs channels.
27
+//
28
+// Log subscriptions are pushed to the work nodes by creating log subscsription
29
+// tasks. As such, the LogBroker also acts as an orchestrator of these tasks.
30
+type LogBroker struct {
31
+	mu                sync.RWMutex
32
+	logQueue          *watch.Queue
33
+	subscriptionQueue *watch.Queue
34
+
35
+	registeredSubscriptions map[string]*api.SubscriptionMessage
36
+
37
+	pctx      context.Context
38
+	cancelAll context.CancelFunc
39
+}
40
+
41
+// New initializes and returns a new LogBroker
42
+func New() *LogBroker {
43
+	return &LogBroker{}
44
+}
45
+
46
+// Run the log broker
47
+func (lb *LogBroker) Run(ctx context.Context) error {
48
+	lb.mu.Lock()
49
+
50
+	if lb.cancelAll != nil {
51
+		lb.mu.Unlock()
52
+		return errAlreadyRunning
53
+	}
54
+
55
+	lb.pctx, lb.cancelAll = context.WithCancel(ctx)
56
+	lb.logQueue = watch.NewQueue()
57
+	lb.subscriptionQueue = watch.NewQueue()
58
+	lb.registeredSubscriptions = make(map[string]*api.SubscriptionMessage)
59
+	lb.mu.Unlock()
60
+
61
+	select {
62
+	case <-lb.pctx.Done():
63
+		return lb.pctx.Err()
64
+	}
65
+}
66
+
67
+// Stop stops the log broker
68
+func (lb *LogBroker) Stop() error {
69
+	lb.mu.Lock()
70
+	defer lb.mu.Unlock()
71
+
72
+	if lb.cancelAll == nil {
73
+		return errNotRunning
74
+	}
75
+	lb.cancelAll()
76
+	lb.cancelAll = nil
77
+
78
+	lb.logQueue.Close()
79
+	lb.subscriptionQueue.Close()
80
+
81
+	return nil
82
+}
83
+
84
+func validateSelector(selector *api.LogSelector) error {
85
+	if selector == nil {
86
+		return grpc.Errorf(codes.InvalidArgument, "log selector must be provided")
87
+	}
88
+
89
+	if len(selector.ServiceIDs) == 0 && len(selector.TaskIDs) == 0 && len(selector.NodeIDs) == 0 {
90
+		return grpc.Errorf(codes.InvalidArgument, "log selector must not be empty")
91
+	}
92
+
93
+	return nil
94
+}
95
+
96
+func (lb *LogBroker) registerSubscription(subscription *api.SubscriptionMessage) {
97
+	lb.mu.Lock()
98
+	defer lb.mu.Unlock()
99
+
100
+	lb.registeredSubscriptions[subscription.ID] = subscription
101
+	lb.subscriptionQueue.Publish(subscription)
102
+}
103
+
104
+func (lb *LogBroker) unregisterSubscription(subscription *api.SubscriptionMessage) {
105
+	subscription = subscription.Copy()
106
+	subscription.Close = true
107
+
108
+	lb.mu.Lock()
109
+	defer lb.mu.Unlock()
110
+
111
+	delete(lb.registeredSubscriptions, subscription.ID)
112
+	lb.subscriptionQueue.Publish(subscription)
113
+}
114
+
115
+func (lb *LogBroker) watchSubscriptions() ([]*api.SubscriptionMessage, chan events.Event, func()) {
116
+	lb.mu.RLock()
117
+	defer lb.mu.RUnlock()
118
+
119
+	subs := make([]*api.SubscriptionMessage, 0, len(lb.registeredSubscriptions))
120
+	for _, sub := range lb.registeredSubscriptions {
121
+		subs = append(subs, sub)
122
+	}
123
+
124
+	ch, cancel := lb.subscriptionQueue.Watch()
125
+	return subs, ch, cancel
126
+}
127
+
128
+func (lb *LogBroker) subscribe(id string) (chan events.Event, func()) {
129
+	lb.mu.RLock()
130
+	defer lb.mu.RUnlock()
131
+
132
+	return lb.logQueue.CallbackWatch(events.MatcherFunc(func(event events.Event) bool {
133
+		publish := event.(*api.PublishLogsMessage)
134
+		return publish.SubscriptionID == id
135
+	}))
136
+}
137
+
138
+func (lb *LogBroker) publish(log *api.PublishLogsMessage) {
139
+	lb.mu.RLock()
140
+	defer lb.mu.RUnlock()
141
+
142
+	lb.logQueue.Publish(log)
143
+}
144
+
145
+// SubscribeLogs creates a log subscription and streams back logs
146
+func (lb *LogBroker) SubscribeLogs(request *api.SubscribeLogsRequest, stream api.Logs_SubscribeLogsServer) error {
147
+	ctx := stream.Context()
148
+
149
+	if err := validateSelector(request.Selector); err != nil {
150
+		return err
151
+	}
152
+
153
+	subscription := &api.SubscriptionMessage{
154
+		ID:       identity.NewID(),
155
+		Selector: request.Selector,
156
+		Options:  request.Options,
157
+	}
158
+
159
+	log := log.G(ctx).WithFields(
160
+		logrus.Fields{
161
+			"method":          "(*LogBroker).SubscribeLogs",
162
+			"subscription.id": subscription.ID,
163
+		},
164
+	)
165
+
166
+	log.Debug("subscribed")
167
+
168
+	publishCh, publishCancel := lb.subscribe(subscription.ID)
169
+	defer publishCancel()
170
+
171
+	lb.registerSubscription(subscription)
172
+	defer lb.unregisterSubscription(subscription)
173
+
174
+	for {
175
+		select {
176
+		case event := <-publishCh:
177
+			publish := event.(*api.PublishLogsMessage)
178
+			if err := stream.Send(&api.SubscribeLogsMessage{
179
+				Messages: publish.Messages,
180
+			}); err != nil {
181
+				return err
182
+			}
183
+		case <-ctx.Done():
184
+			return ctx.Err()
185
+		case <-lb.pctx.Done():
186
+			return nil
187
+		}
188
+	}
189
+}
190
+
191
+// ListenSubscriptions returns a stream of matching subscriptions for the current node
192
+func (lb *LogBroker) ListenSubscriptions(request *api.ListenSubscriptionsRequest, stream api.LogBroker_ListenSubscriptionsServer) error {
193
+	remote, err := ca.RemoteNode(stream.Context())
194
+	if err != nil {
195
+		return err
196
+	}
197
+
198
+	log := log.G(stream.Context()).WithFields(
199
+		logrus.Fields{
200
+			"method": "(*LogBroker).ListenSubscriptions",
201
+			"node":   remote.NodeID,
202
+		},
203
+	)
204
+	subscriptions, subscriptionCh, subscriptionCancel := lb.watchSubscriptions()
205
+	defer subscriptionCancel()
206
+
207
+	log.Debug("node registered")
208
+
209
+	// Start by sending down all active subscriptions.
210
+	for _, subscription := range subscriptions {
211
+		select {
212
+		case <-stream.Context().Done():
213
+			return stream.Context().Err()
214
+		case <-lb.pctx.Done():
215
+			return nil
216
+		default:
217
+		}
218
+
219
+		if err := stream.Send(subscription); err != nil {
220
+			log.Error(err)
221
+			return err
222
+		}
223
+	}
224
+
225
+	// Send down new subscriptions.
226
+	// TODO(aluzzardi): We should filter by relevant tasks for this node rather
227
+	for {
228
+		select {
229
+		case v := <-subscriptionCh:
230
+			subscription := v.(*api.SubscriptionMessage)
231
+			if err := stream.Send(subscription); err != nil {
232
+				log.Error(err)
233
+				return err
234
+			}
235
+		case <-stream.Context().Done():
236
+			return stream.Context().Err()
237
+		case <-lb.pctx.Done():
238
+			return nil
239
+		}
240
+	}
241
+}
242
+
243
+// PublishLogs publishes log messages for a given subscription
244
+func (lb *LogBroker) PublishLogs(stream api.LogBroker_PublishLogsServer) error {
245
+	remote, err := ca.RemoteNode(stream.Context())
246
+	if err != nil {
247
+		return err
248
+	}
249
+
250
+	for {
251
+		log, err := stream.Recv()
252
+		if err == io.EOF {
253
+			return stream.SendAndClose(&api.PublishLogsResponse{})
254
+		}
255
+		if err != nil {
256
+			return err
257
+		}
258
+
259
+		if log.SubscriptionID == "" {
260
+			return grpc.Errorf(codes.InvalidArgument, "missing subscription ID")
261
+		}
262
+
263
+		// Make sure logs are emitted using the right Node ID to avoid impersonation.
264
+		for _, msg := range log.Messages {
265
+			if msg.Context.NodeID != remote.NodeID {
266
+				return grpc.Errorf(codes.PermissionDenied, "invalid NodeID: expected=%s;received=%s", remote.NodeID, msg.Context.NodeID)
267
+			}
268
+		}
269
+
270
+		lb.publish(log)
271
+	}
272
+}
... ...
@@ -22,6 +22,7 @@ import (
22 22
 	"github.com/docker/swarmkit/manager/dispatcher"
23 23
 	"github.com/docker/swarmkit/manager/health"
24 24
 	"github.com/docker/swarmkit/manager/keymanager"
25
+	"github.com/docker/swarmkit/manager/logbroker"
25 26
 	"github.com/docker/swarmkit/manager/orchestrator/constraintenforcer"
26 27
 	"github.com/docker/swarmkit/manager/orchestrator/global"
27 28
 	"github.com/docker/swarmkit/manager/orchestrator/replicated"
... ...
@@ -96,6 +97,7 @@ type Manager struct {
96 96
 
97 97
 	caserver               *ca.Server
98 98
 	dispatcher             *dispatcher.Dispatcher
99
+	logbroker              *logbroker.LogBroker
99 100
 	replicatedOrchestrator *replicated.Orchestrator
100 101
 	globalOrchestrator     *global.Orchestrator
101 102
 	taskReaper             *taskreaper.TaskReaper
... ...
@@ -234,6 +236,7 @@ func New(config *Config) (*Manager, error) {
234 234
 		listeners:   listeners,
235 235
 		caserver:    ca.NewServer(raftNode.MemoryStore(), config.SecurityConfig),
236 236
 		dispatcher:  dispatcher.New(raftNode, dispatcherConfig),
237
+		logbroker:   logbroker.New(),
237 238
 		server:      grpc.NewServer(opts...),
238 239
 		localserver: grpc.NewServer(opts...),
239 240
 		raftNode:    raftNode,
... ...
@@ -292,6 +295,8 @@ func (m *Manager) Run(parent context.Context) error {
292 292
 
293 293
 	authenticatedControlAPI := api.NewAuthenticatedWrapperControlServer(baseControlAPI, authorize)
294 294
 	authenticatedResourceAPI := api.NewAuthenticatedWrapperResourceAllocatorServer(baseResourceAPI, authorize)
295
+	authenticatedLogsServerAPI := api.NewAuthenticatedWrapperLogsServer(m.logbroker, authorize)
296
+	authenticatedLogBrokerAPI := api.NewAuthenticatedWrapperLogBrokerServer(m.logbroker, authorize)
295 297
 	authenticatedDispatcherAPI := api.NewAuthenticatedWrapperDispatcherServer(m.dispatcher, authorize)
296 298
 	authenticatedCAAPI := api.NewAuthenticatedWrapperCAServer(m.caserver, authorize)
297 299
 	authenticatedNodeCAAPI := api.NewAuthenticatedWrapperNodeCAServer(m.caserver, authorize)
... ...
@@ -304,6 +309,7 @@ func (m *Manager) Run(parent context.Context) error {
304 304
 	proxyNodeCAAPI := api.NewRaftProxyNodeCAServer(authenticatedNodeCAAPI, m.raftNode, ca.WithMetadataForwardTLSInfo)
305 305
 	proxyRaftMembershipAPI := api.NewRaftProxyRaftMembershipServer(authenticatedRaftMembershipAPI, m.raftNode, ca.WithMetadataForwardTLSInfo)
306 306
 	proxyResourceAPI := api.NewRaftProxyResourceAllocatorServer(authenticatedResourceAPI, m.raftNode, ca.WithMetadataForwardTLSInfo)
307
+	proxyLogBrokerAPI := api.NewRaftProxyLogBrokerServer(authenticatedLogBrokerAPI, m.raftNode, ca.WithMetadataForwardTLSInfo)
307 308
 
308 309
 	// localProxyControlAPI is a special kind of proxy. It is only wired up
309 310
 	// to receive requests from a trusted local socket, and these requests
... ...
@@ -313,6 +319,7 @@ func (m *Manager) Run(parent context.Context) error {
313 313
 	// information to put in the metadata map).
314 314
 	forwardAsOwnRequest := func(ctx context.Context) (context.Context, error) { return ctx, nil }
315 315
 	localProxyControlAPI := api.NewRaftProxyControlServer(baseControlAPI, m.raftNode, forwardAsOwnRequest)
316
+	localProxyLogsAPI := api.NewRaftProxyLogsServer(m.logbroker, m.raftNode, forwardAsOwnRequest)
316 317
 
317 318
 	// Everything registered on m.server should be an authenticated
318 319
 	// wrapper, or a proxy wrapping an authenticated wrapper!
... ...
@@ -322,10 +329,13 @@ func (m *Manager) Run(parent context.Context) error {
322 322
 	api.RegisterHealthServer(m.server, authenticatedHealthAPI)
323 323
 	api.RegisterRaftMembershipServer(m.server, proxyRaftMembershipAPI)
324 324
 	api.RegisterControlServer(m.server, authenticatedControlAPI)
325
+	api.RegisterLogsServer(m.server, authenticatedLogsServerAPI)
326
+	api.RegisterLogBrokerServer(m.server, proxyLogBrokerAPI)
325 327
 	api.RegisterResourceAllocatorServer(m.server, proxyResourceAPI)
326 328
 	api.RegisterDispatcherServer(m.server, proxyDispatcherAPI)
327 329
 
328 330
 	api.RegisterControlServer(m.localserver, localProxyControlAPI)
331
+	api.RegisterLogsServer(m.localserver, localProxyLogsAPI)
329 332
 	api.RegisterHealthServer(m.localserver, localHealthServer)
330 333
 
331 334
 	healthServer.SetServingStatus("Raft", api.HealthCheckResponse_NOT_SERVING)
... ...
@@ -419,6 +429,7 @@ func (m *Manager) Stop(ctx context.Context) {
419 419
 	}()
420 420
 
421 421
 	m.dispatcher.Stop()
422
+	m.logbroker.Stop()
422 423
 	m.caserver.Stop()
423 424
 
424 425
 	if m.allocator != nil {
... ...
@@ -664,6 +675,12 @@ func (m *Manager) becomeLeader(ctx context.Context) {
664 664
 		}
665 665
 	}(m.dispatcher)
666 666
 
667
+	go func(lb *logbroker.LogBroker) {
668
+		if err := lb.Run(ctx); err != nil {
669
+			log.G(ctx).WithError(err).Error("LogBroker exited with an error")
670
+		}
671
+	}(m.logbroker)
672
+
667 673
 	go func(server *ca.Server) {
668 674
 		if err := server.Run(ctx); err != nil {
669 675
 			log.G(ctx).WithError(err).Error("CA signer exited with an error")
... ...
@@ -712,6 +729,7 @@ func (m *Manager) becomeLeader(ctx context.Context) {
712 712
 // becomeFollower shuts down the subsystems that are only run by the leader.
713 713
 func (m *Manager) becomeFollower() {
714 714
 	m.dispatcher.Stop()
715
+	m.logbroker.Stop()
715 716
 	m.caserver.Stop()
716 717
 
717 718
 	if m.allocator != nil {
... ...
@@ -478,6 +478,9 @@ func (g *Orchestrator) addTask(ctx context.Context, batch *store.Batch, service
478 478
 	task := orchestrator.NewTask(g.cluster, service, 0, nodeID)
479 479
 
480 480
 	err := batch.Update(func(tx store.Tx) error {
481
+		if store.GetService(tx, service.ID) == nil {
482
+			return nil
483
+		}
481 484
 		return store.CreateTask(tx, task)
482 485
 	})
483 486
 	if err != nil {
... ...
@@ -53,6 +53,7 @@ func (r *Orchestrator) handleServiceEvent(ctx context.Context, event events.Even
53 53
 		}
54 54
 		orchestrator.DeleteServiceTasks(ctx, r.store, v.Service)
55 55
 		r.restarts.ClearServiceHistory(v.Service.ID)
56
+		delete(r.reconcileServices, v.Service.ID)
56 57
 	case state.EventCreateService:
57 58
 		if !orchestrator.IsReplicatedService(v.Service) {
58 59
 			return
... ...
@@ -16,8 +16,8 @@ import (
16 16
 	"github.com/docker/swarmkit/manager/orchestrator/restart"
17 17
 	"github.com/docker/swarmkit/manager/state"
18 18
 	"github.com/docker/swarmkit/manager/state/store"
19
-	"github.com/docker/swarmkit/manager/state/watch"
20 19
 	"github.com/docker/swarmkit/protobuf/ptypes"
20
+	"github.com/docker/swarmkit/watch"
21 21
 )
22 22
 
23 23
 const defaultMonitor = 30 * time.Second
... ...
@@ -383,6 +383,10 @@ func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, update
383 383
 		}
384 384
 
385 385
 		err = batch.Update(func(tx store.Tx) error {
386
+			if store.GetService(tx, updated.ServiceID) == nil {
387
+				return errors.New("service was deleted")
388
+			}
389
+
386 390
 			if err := store.CreateTask(tx, updated); err != nil {
387 391
 				return err
388 392
 			}
... ...
@@ -9,7 +9,7 @@ import (
9 9
 
10 10
 	"github.com/coreos/etcd/raft/raftpb"
11 11
 	"github.com/docker/swarmkit/api"
12
-	"github.com/docker/swarmkit/manager/state/watch"
12
+	"github.com/docker/swarmkit/watch"
13 13
 	"github.com/gogo/protobuf/proto"
14 14
 	"golang.org/x/net/context"
15 15
 )
... ...
@@ -29,7 +29,7 @@ import (
29 29
 	"github.com/docker/swarmkit/manager/raftselector"
30 30
 	"github.com/docker/swarmkit/manager/state/raft/membership"
31 31
 	"github.com/docker/swarmkit/manager/state/store"
32
-	"github.com/docker/swarmkit/manager/state/watch"
32
+	"github.com/docker/swarmkit/watch"
33 33
 	"github.com/gogo/protobuf/proto"
34 34
 	"github.com/pivotal-golang/clock"
35 35
 	"github.com/pkg/errors"
... ...
@@ -121,3 +121,25 @@ func (b byMembership) isBy() {
121 121
 func ByMembership(membership api.NodeSpec_Membership) By {
122 122
 	return byMembership(membership)
123 123
 }
124
+
125
+type byReferencedNetworkID string
126
+
127
+func (b byReferencedNetworkID) isBy() {
128
+}
129
+
130
+// ByReferencedNetworkID creates an object to pass to Find to search for a
131
+// service or task that references a network with the given ID.
132
+func ByReferencedNetworkID(networkID string) By {
133
+	return byReferencedNetworkID(networkID)
134
+}
135
+
136
+type byReferencedSecretID string
137
+
138
+func (b byReferencedSecretID) isBy() {
139
+}
140
+
141
+// ByReferencedSecretID creates an object to pass to Find to search for a
142
+// service or task that references a secret with the given ID.
143
+func ByReferencedSecretID(secretID string) By {
144
+	return byReferencedSecretID(secretID)
145
+}
... ...
@@ -13,8 +13,8 @@ import (
13 13
 	"github.com/docker/swarmkit/api"
14 14
 	pb "github.com/docker/swarmkit/api"
15 15
 	"github.com/docker/swarmkit/manager/state"
16
-	"github.com/docker/swarmkit/manager/state/watch"
17 16
 	"github.com/docker/swarmkit/protobuf/ptypes"
17
+	"github.com/docker/swarmkit/watch"
18 18
 	memdb "github.com/hashicorp/go-memdb"
19 19
 	"golang.org/x/net/context"
20 20
 )
... ...
@@ -29,6 +29,8 @@ const (
29 29
 	indexDesiredState = "desiredstate"
30 30
 	indexRole         = "role"
31 31
 	indexMembership   = "membership"
32
+	indexNetwork      = "network"
33
+	indexSecret       = "secret"
32 34
 
33 35
 	prefix = "_prefix"
34 36
 
... ...
@@ -624,6 +626,18 @@ func (tx readTx) findIterators(table string, by By, checkType func(By) error) ([
624 624
 			return nil, err
625 625
 		}
626 626
 		return []memdb.ResultIterator{it}, nil
627
+	case byReferencedNetworkID:
628
+		it, err := tx.memDBTx.Get(table, indexNetwork, string(v))
629
+		if err != nil {
630
+			return nil, err
631
+		}
632
+		return []memdb.ResultIterator{it}, nil
633
+	case byReferencedSecretID:
634
+		it, err := tx.memDBTx.Get(table, indexSecret, string(v))
635
+		if err != nil {
636
+			return nil, err
637
+		}
638
+		return []memdb.ResultIterator{it}, nil
627 639
 	default:
628 640
 		return nil, ErrInvalidFindBy
629 641
 	}
... ...
@@ -26,6 +26,16 @@ func init() {
26 26
 					Unique:  true,
27 27
 					Indexer: serviceIndexerByName{},
28 28
 				},
29
+				indexNetwork: {
30
+					Name:         indexNetwork,
31
+					AllowMissing: true,
32
+					Indexer:      serviceIndexerByNetwork{},
33
+				},
34
+				indexSecret: {
35
+					Name:         indexSecret,
36
+					AllowMissing: true,
37
+					Indexer:      serviceIndexerBySecret{},
38
+				},
29 39
 			},
30 40
 		},
31 41
 		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
... ...
@@ -167,7 +177,7 @@ func GetService(tx ReadTx, id string) *api.Service {
167 167
 func FindServices(tx ReadTx, by By) ([]*api.Service, error) {
168 168
 	checkType := func(by By) error {
169 169
 		switch by.(type) {
170
-		case byName, byNamePrefix, byIDPrefix:
170
+		case byName, byNamePrefix, byIDPrefix, byReferencedNetworkID, byReferencedSecretID:
171 171
 			return nil
172 172
 		default:
173 173
 			return ErrInvalidFindBy
... ...
@@ -223,3 +233,58 @@ func (si serviceIndexerByName) FromObject(obj interface{}) (bool, []byte, error)
223 223
 func (si serviceIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
224 224
 	return prefixFromArgs(args...)
225 225
 }
226
+
227
+type serviceIndexerByNetwork struct{}
228
+
229
+func (si serviceIndexerByNetwork) FromArgs(args ...interface{}) ([]byte, error) {
230
+	return fromArgs(args...)
231
+}
232
+
233
+func (si serviceIndexerByNetwork) FromObject(obj interface{}) (bool, [][]byte, error) {
234
+	s, ok := obj.(serviceEntry)
235
+	if !ok {
236
+		panic("unexpected type passed to FromObject")
237
+	}
238
+
239
+	var networkIDs [][]byte
240
+
241
+	specNetworks := s.Spec.Task.Networks
242
+
243
+	if len(specNetworks) == 0 {
244
+		specNetworks = s.Spec.Networks
245
+	}
246
+
247
+	for _, na := range specNetworks {
248
+		// Add the null character as a terminator
249
+		networkIDs = append(networkIDs, []byte(na.Target+"\x00"))
250
+	}
251
+
252
+	return len(networkIDs) != 0, networkIDs, nil
253
+}
254
+
255
+type serviceIndexerBySecret struct{}
256
+
257
+func (si serviceIndexerBySecret) FromArgs(args ...interface{}) ([]byte, error) {
258
+	return fromArgs(args...)
259
+}
260
+
261
+func (si serviceIndexerBySecret) FromObject(obj interface{}) (bool, [][]byte, error) {
262
+	s, ok := obj.(serviceEntry)
263
+	if !ok {
264
+		panic("unexpected type passed to FromObject")
265
+	}
266
+
267
+	container := s.Spec.Task.GetContainer()
268
+	if container == nil {
269
+		return false, nil, nil
270
+	}
271
+
272
+	var secretIDs [][]byte
273
+
274
+	for _, secretRef := range container.Secrets {
275
+		// Add the null character as a terminator
276
+		secretIDs = append(secretIDs, []byte(secretRef.SecretID+"\x00"))
277
+	}
278
+
279
+	return len(secretIDs) != 0, secretIDs, nil
280
+}
... ...
@@ -47,6 +47,16 @@ func init() {
47 47
 					Name:    indexDesiredState,
48 48
 					Indexer: taskIndexerByDesiredState{},
49 49
 				},
50
+				indexNetwork: {
51
+					Name:         indexNetwork,
52
+					AllowMissing: true,
53
+					Indexer:      taskIndexerByNetwork{},
54
+				},
55
+				indexSecret: {
56
+					Name:         indexSecret,
57
+					AllowMissing: true,
58
+					Indexer:      taskIndexerBySecret{},
59
+				},
50 60
 			},
51 61
 		},
52 62
 		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
... ...
@@ -176,7 +186,7 @@ func GetTask(tx ReadTx, id string) *api.Task {
176 176
 func FindTasks(tx ReadTx, by By) ([]*api.Task, error) {
177 177
 	checkType := func(by By) error {
178 178
 		switch by.(type) {
179
-		case byName, byNamePrefix, byIDPrefix, byDesiredState, byNode, byService, bySlot:
179
+		case byName, byNamePrefix, byIDPrefix, byDesiredState, byNode, byService, bySlot, byReferencedNetworkID, byReferencedSecretID:
180 180
 			return nil
181 181
 		default:
182 182
 			return ErrInvalidFindBy
... ...
@@ -288,16 +298,65 @@ func (ti taskIndexerBySlot) FromObject(obj interface{}) (bool, []byte, error) {
288 288
 
289 289
 type taskIndexerByDesiredState struct{}
290 290
 
291
-func (ni taskIndexerByDesiredState) FromArgs(args ...interface{}) ([]byte, error) {
291
+func (ti taskIndexerByDesiredState) FromArgs(args ...interface{}) ([]byte, error) {
292 292
 	return fromArgs(args...)
293 293
 }
294 294
 
295
-func (ni taskIndexerByDesiredState) FromObject(obj interface{}) (bool, []byte, error) {
296
-	n, ok := obj.(taskEntry)
295
+func (ti taskIndexerByDesiredState) FromObject(obj interface{}) (bool, []byte, error) {
296
+	t, ok := obj.(taskEntry)
297 297
 	if !ok {
298 298
 		panic("unexpected type passed to FromObject")
299 299
 	}
300 300
 
301 301
 	// Add the null character as a terminator
302
-	return true, []byte(strconv.FormatInt(int64(n.DesiredState), 10) + "\x00"), nil
302
+	return true, []byte(strconv.FormatInt(int64(t.DesiredState), 10) + "\x00"), nil
303
+}
304
+
305
+type taskIndexerByNetwork struct{}
306
+
307
+func (ti taskIndexerByNetwork) FromArgs(args ...interface{}) ([]byte, error) {
308
+	return fromArgs(args...)
309
+}
310
+
311
+func (ti taskIndexerByNetwork) FromObject(obj interface{}) (bool, [][]byte, error) {
312
+	t, ok := obj.(taskEntry)
313
+	if !ok {
314
+		panic("unexpected type passed to FromObject")
315
+	}
316
+
317
+	var networkIDs [][]byte
318
+
319
+	for _, na := range t.Spec.Networks {
320
+		// Add the null character as a terminator
321
+		networkIDs = append(networkIDs, []byte(na.Target+"\x00"))
322
+	}
323
+
324
+	return len(networkIDs) != 0, networkIDs, nil
325
+}
326
+
327
+type taskIndexerBySecret struct{}
328
+
329
+func (ti taskIndexerBySecret) FromArgs(args ...interface{}) ([]byte, error) {
330
+	return fromArgs(args...)
331
+}
332
+
333
+func (ti taskIndexerBySecret) FromObject(obj interface{}) (bool, [][]byte, error) {
334
+	t, ok := obj.(taskEntry)
335
+	if !ok {
336
+		panic("unexpected type passed to FromObject")
337
+	}
338
+
339
+	container := t.Spec.GetContainer()
340
+	if container == nil {
341
+		return false, nil, nil
342
+	}
343
+
344
+	var secretIDs [][]byte
345
+
346
+	for _, secretRef := range container.Secrets {
347
+		// Add the null character as a terminator
348
+		secretIDs = append(secretIDs, []byte(secretRef.SecretID+"\x00"))
349
+	}
350
+
351
+	return len(secretIDs) != 0, secretIDs, nil
303 352
 }
... ...
@@ -3,7 +3,7 @@ package state
3 3
 import (
4 4
 	"github.com/docker/go-events"
5 5
 	"github.com/docker/swarmkit/api"
6
-	"github.com/docker/swarmkit/manager/state/watch"
6
+	"github.com/docker/swarmkit/watch"
7 7
 )
8 8
 
9 9
 // Event is the type used for events passed over watcher channels, and also
10 10
deleted file mode 100644
... ...
@@ -1,107 +0,0 @@
1
-package watch
2
-
3
-import (
4
-	"sync"
5
-
6
-	"github.com/docker/go-events"
7
-)
8
-
9
-// dropErrClosed is a sink that suppresses ErrSinkClosed from Write, to avoid
10
-// debug log messages that may be confusing. It is possible that the queue
11
-// will try to write an event to its destination channel while the queue is
12
-// being removed from the broadcaster. Since the channel is closed before the
13
-// queue, there is a narrow window when this is possible. In some event-based
14
-// dropping events when a sink is removed from a broadcaster is a problem, but
15
-// for the usage in this watch package that's the expected behavior.
16
-type dropErrClosed struct {
17
-	sink events.Sink
18
-}
19
-
20
-func (s dropErrClosed) Write(event events.Event) error {
21
-	err := s.sink.Write(event)
22
-	if err == events.ErrSinkClosed {
23
-		return nil
24
-	}
25
-	return err
26
-}
27
-
28
-func (s dropErrClosed) Close() error {
29
-	return s.sink.Close()
30
-}
31
-
32
-// Queue is the structure used to publish events and watch for them.
33
-type Queue struct {
34
-	mu          sync.Mutex
35
-	broadcast   *events.Broadcaster
36
-	cancelFuncs map[*events.Channel]func()
37
-}
38
-
39
-// NewQueue creates a new publish/subscribe queue which supports watchers.
40
-// The channels that it will create for subscriptions will have the buffer
41
-// size specified by buffer.
42
-func NewQueue() *Queue {
43
-	return &Queue{
44
-		broadcast:   events.NewBroadcaster(),
45
-		cancelFuncs: make(map[*events.Channel]func()),
46
-	}
47
-}
48
-
49
-// Watch returns a channel which will receive all items published to the
50
-// queue from this point, until cancel is called.
51
-func (q *Queue) Watch() (eventq chan events.Event, cancel func()) {
52
-	return q.CallbackWatch(nil)
53
-}
54
-
55
-// CallbackWatch returns a channel which will receive all events published to
56
-// the queue from this point that pass the check in the provided callback
57
-// function. The returned cancel function will stop the flow of events and
58
-// close the channel.
59
-func (q *Queue) CallbackWatch(matcher events.Matcher) (eventq chan events.Event, cancel func()) {
60
-	ch := events.NewChannel(0)
61
-	sink := events.Sink(events.NewQueue(dropErrClosed{sink: ch}))
62
-
63
-	if matcher != nil {
64
-		sink = events.NewFilter(sink, matcher)
65
-	}
66
-
67
-	q.broadcast.Add(sink)
68
-
69
-	cancelFunc := func() {
70
-		q.broadcast.Remove(sink)
71
-		ch.Close()
72
-		sink.Close()
73
-	}
74
-
75
-	q.mu.Lock()
76
-	q.cancelFuncs[ch] = cancelFunc
77
-	q.mu.Unlock()
78
-	return ch.C, func() {
79
-		q.mu.Lock()
80
-		cancelFunc := q.cancelFuncs[ch]
81
-		delete(q.cancelFuncs, ch)
82
-		q.mu.Unlock()
83
-
84
-		if cancelFunc != nil {
85
-			cancelFunc()
86
-		}
87
-	}
88
-}
89
-
90
-// Publish adds an item to the queue.
91
-func (q *Queue) Publish(item events.Event) {
92
-	q.broadcast.Write(item)
93
-}
94
-
95
-// Close closes the queue and frees the associated resources.
96
-func (q *Queue) Close() error {
97
-	// Make sure all watchers have been closed to avoid a deadlock when
98
-	// closing the broadcaster.
99
-	q.mu.Lock()
100
-	for _, cancelFunc := range q.cancelFuncs {
101
-		cancelFunc()
102
-	}
103
-	q.cancelFuncs = make(map[*events.Channel]func())
104
-	q.mu.Unlock()
105
-
106
-	return q.broadcast.Close()
107
-}
108 1
new file mode 100644
... ...
@@ -0,0 +1,107 @@
0
+package watch
1
+
2
+import (
3
+	"sync"
4
+
5
+	"github.com/docker/go-events"
6
+)
7
+
8
+// dropErrClosed is a sink that suppresses ErrSinkClosed from Write, to avoid
9
+// debug log messages that may be confusing. It is possible that the queue
10
+// will try to write an event to its destination channel while the queue is
11
+// being removed from the broadcaster. Since the channel is closed before the
12
+// queue, there is a narrow window when this is possible. In some event-based
13
+// dropping events when a sink is removed from a broadcaster is a problem, but
14
+// for the usage in this watch package that's the expected behavior.
15
+type dropErrClosed struct {
16
+	sink events.Sink
17
+}
18
+
19
+func (s dropErrClosed) Write(event events.Event) error {
20
+	err := s.sink.Write(event)
21
+	if err == events.ErrSinkClosed {
22
+		return nil
23
+	}
24
+	return err
25
+}
26
+
27
+func (s dropErrClosed) Close() error {
28
+	return s.sink.Close()
29
+}
30
+
31
+// Queue is the structure used to publish events and watch for them.
32
+type Queue struct {
33
+	mu          sync.Mutex
34
+	broadcast   *events.Broadcaster
35
+	cancelFuncs map[*events.Channel]func()
36
+}
37
+
38
+// NewQueue creates a new publish/subscribe queue which supports watchers.
39
+// The channels that it will create for subscriptions will have the buffer
40
+// size specified by buffer.
41
+func NewQueue() *Queue {
42
+	return &Queue{
43
+		broadcast:   events.NewBroadcaster(),
44
+		cancelFuncs: make(map[*events.Channel]func()),
45
+	}
46
+}
47
+
48
+// Watch returns a channel which will receive all items published to the
49
+// queue from this point, until cancel is called.
50
+func (q *Queue) Watch() (eventq chan events.Event, cancel func()) {
51
+	return q.CallbackWatch(nil)
52
+}
53
+
54
+// CallbackWatch returns a channel which will receive all events published to
55
+// the queue from this point that pass the check in the provided callback
56
+// function. The returned cancel function will stop the flow of events and
57
+// close the channel.
58
+func (q *Queue) CallbackWatch(matcher events.Matcher) (eventq chan events.Event, cancel func()) {
59
+	ch := events.NewChannel(0)
60
+	sink := events.Sink(events.NewQueue(dropErrClosed{sink: ch}))
61
+
62
+	if matcher != nil {
63
+		sink = events.NewFilter(sink, matcher)
64
+	}
65
+
66
+	q.broadcast.Add(sink)
67
+
68
+	cancelFunc := func() {
69
+		q.broadcast.Remove(sink)
70
+		ch.Close()
71
+		sink.Close()
72
+	}
73
+
74
+	q.mu.Lock()
75
+	q.cancelFuncs[ch] = cancelFunc
76
+	q.mu.Unlock()
77
+	return ch.C, func() {
78
+		q.mu.Lock()
79
+		cancelFunc := q.cancelFuncs[ch]
80
+		delete(q.cancelFuncs, ch)
81
+		q.mu.Unlock()
82
+
83
+		if cancelFunc != nil {
84
+			cancelFunc()
85
+		}
86
+	}
87
+}
88
+
89
+// Publish adds an item to the queue.
90
+func (q *Queue) Publish(item events.Event) {
91
+	q.broadcast.Write(item)
92
+}
93
+
94
+// Close closes the queue and frees the associated resources.
95
+func (q *Queue) Close() error {
96
+	// Make sure all watchers have been closed to avoid a deadlock when
97
+	// closing the broadcaster.
98
+	q.mu.Lock()
99
+	for _, cancelFunc := range q.cancelFuncs {
100
+		cancelFunc()
101
+	}
102
+	q.cancelFuncs = make(map[*events.Channel]func())
103
+	q.mu.Unlock()
104
+
105
+	return q.broadcast.Close()
106
+}