Skip to content

Commit 53ae288

Browse files
authored
Merge pull request #3210 from corhere/network-allocator-controlapi-hooks
Afford NetworkAllocator passing per-app state in Control API responses
2 parents a45be3c + 8feab8a commit 53ae288

12 files changed

Lines changed: 286 additions & 117 deletions

File tree

api/api.pb.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7215,6 +7215,14 @@ file {
72157215
type: TYPE_BOOL
72167216
json_name: "pendingDelete"
72177217
}
7218+
field {
7219+
name: "extra"
7220+
number: 7
7221+
label: LABEL_OPTIONAL
7222+
type: TYPE_MESSAGE
7223+
type_name: ".google.protobuf.Any"
7224+
json_name: "extra"
7225+
}
72187226
options {
72197227
70001 {
72207228
1 {

api/objects.pb.go

Lines changed: 175 additions & 113 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/objects.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ message Network {
332332
// the services that still use this service, and proceed to delete
333333
// this network when all of these services are gone
334334
bool pending_delete = 6;
335+
336+
// Extra encodes application-specific information about the live state
337+
// of the network. The syntax and semantics of the value are dictated by
338+
// the network allocator implementation.
339+
google.protobuf.Any extra = 7;
335340
}
336341

337342
// Cluster provides global cluster settings.

manager/allocator/network.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,10 @@ func (a *Allocator) procTasksNetwork(ctx context.Context, onRetry bool) {
15241524
}
15251525
}
15261526

1527+
func (a *Allocator) NetworkAllocator() networkallocator.NetworkAllocator {
1528+
return a.nwkAllocator
1529+
}
1530+
15271531
// updateTaskStatus sets TaskStatus and updates timestamp.
15281532
func updateTaskStatus(t *api.Task, newStatus api.TaskState, message string) {
15291533
t.Status = api.TaskStatus{

manager/allocator/networkallocator/networkallocator.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package networkallocator
22

33
import (
4+
"context"
5+
46
"github.com/moby/swarmkit/v2/api"
57
)
68

@@ -87,6 +89,23 @@ type NetworkAllocator interface {
8789
IsAttachmentAllocated(node *api.Node, networkAttachment *api.NetworkAttachment) bool
8890
}
8991

92+
// OnGetNetworker is an optional interface that [NetworkAllocator] may implement
93+
// to customize the Control API response for GetNetwork and ListNetworks requests.
94+
type OnGetNetworker interface {
95+
// OnGetNetwork is called with a copy of the network object that will be
96+
// returned in a GetNetwork or ListNetworks Control API response. Any
97+
// modifications to the network object will be reflected in the
98+
// response. The modified network object will not be persisted to the
99+
// store. Errors returned will be bubbled up to the Control API client.
100+
//
101+
// The network may not have been allocated at the time of the call.
102+
// Calling OnGetNetwork with an unallocated network should not be an
103+
// error.
104+
//
105+
// This method may be called concurrently from multiple goroutines.
106+
OnGetNetwork(context.Context, *api.Network) error
107+
}
108+
90109
// Config is used to store network related cluster config in the Manager.
91110
type Config struct {
92111
// DefaultAddrPool specifies default subnet pool for global scope networks

manager/apihooks.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package manager
2+
3+
import (
4+
"context"
5+
6+
"github.com/moby/swarmkit/v2/api"
7+
"github.com/moby/swarmkit/v2/manager/allocator/networkallocator"
8+
)
9+
10+
func (m *Manager) networkAllocator() networkallocator.NetworkAllocator {
11+
m.mu.Lock()
12+
defer m.mu.Unlock()
13+
if m.allocator == nil {
14+
return nil
15+
}
16+
return m.allocator.NetworkAllocator()
17+
}
18+
19+
func (m *Manager) OnGetNetwork(ctx context.Context, n *api.Network) error {
20+
if nwh, ok := m.networkAllocator().(networkallocator.OnGetNetworker); ok {
21+
return nwh.OnGetNetwork(ctx, n)
22+
}
23+
return nil
24+
}
25+
26+
func (m *Manager) OnListNetworks(ctx context.Context, networks []*api.Network) error {
27+
if nwh, ok := m.networkAllocator().(networkallocator.OnGetNetworker); ok {
28+
for _, n := range networks {
29+
if err := nwh.OnGetNetwork(ctx, n); err != nil {
30+
return err
31+
}
32+
}
33+
}
34+
return nil
35+
}

manager/controlapi/apihooks.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package controlapi
2+
3+
import (
4+
"context"
5+
6+
"github.com/moby/swarmkit/v2/api"
7+
)
8+
9+
// ViewResponseMutator provides callbacks which may modify the response objects
10+
// for Get or List Control API requests before they are sent to the client.
11+
type ViewResponseMutator interface {
12+
OnGetNetwork(context.Context, *api.Network) error
13+
OnListNetworks(context.Context, []*api.Network) error
14+
}
15+
16+
type NoopViewResponseMutator struct{}
17+
18+
func (NoopViewResponseMutator) OnGetNetwork(ctx context.Context, n *api.Network) error {
19+
return nil
20+
}
21+
22+
func (NoopViewResponseMutator) OnListNetworks(ctx context.Context, networks []*api.Network) error {
23+
return nil
24+
}

manager/controlapi/network.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ func (s *Server) GetNetwork(ctx context.Context, request *api.GetNetworkRequest)
148148
if n == nil {
149149
return nil, status.Errorf(codes.NotFound, "network %s not found", request.NetworkID)
150150
}
151+
if err := s.viewhooks.OnGetNetwork(ctx, n); err != nil {
152+
return nil, err
153+
}
151154
return &api.GetNetworkResponse{
152155
Network: n,
153156
}, nil
@@ -292,6 +295,10 @@ func (s *Server) ListNetworks(ctx context.Context, request *api.ListNetworksRequ
292295
)
293296
}
294297

298+
if err := s.viewhooks.OnListNetworks(ctx, networks); err != nil {
299+
return nil, err
300+
}
301+
295302
return &api.ListNetworksResponse{
296303
Networks: networks,
297304
}, nil

manager/controlapi/server.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,24 @@ type Server struct {
2020
raft *raft.Node
2121
securityConfig *ca.SecurityConfig
2222
netvalidator networkallocator.DriverValidator
23+
viewhooks ViewResponseMutator
2324
dr *drivers.DriverProvider
2425
}
2526

2627
// NewServer creates a Cluster API server.
27-
func NewServer(store *store.MemoryStore, raft *raft.Node, securityConfig *ca.SecurityConfig, nv networkallocator.DriverValidator, dr *drivers.DriverProvider) *Server {
28+
func NewServer(store *store.MemoryStore, raft *raft.Node, securityConfig *ca.SecurityConfig, nv networkallocator.DriverValidator, vrm ViewResponseMutator, dr *drivers.DriverProvider) *Server {
2829
if nv == nil {
2930
nv = networkallocator.InertProvider{}
3031
}
32+
if vrm == nil {
33+
vrm = NoopViewResponseMutator{}
34+
}
3135
return &Server{
3236
store: store,
3337
dr: dr,
3438
raft: raft,
3539
securityConfig: securityConfig,
3640
netvalidator: nv,
41+
viewhooks: vrm,
3742
}
3843
}

manager/controlapi/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func newTestServer(t *testing.T) *testServer {
4747
ts.Store = store.NewMemoryStore(&stateutils.MockProposer{})
4848
assert.NotNil(t, ts.Store)
4949

50-
ts.Server = NewServer(ts.Store, nil, securityConfig, nil, nil)
50+
ts.Server = NewServer(ts.Store, nil, securityConfig, nil, nil, nil)
5151
assert.NotNil(t, ts.Server)
5252

5353
temp, err := os.CreateTemp("", "test-socket")

0 commit comments

Comments
 (0)