nanoping-api 11.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nanoping_api/__init__.py +18 -0
- nanoping_api/_client.py +154 -0
- nanoping_api/_generated.py +4182 -0
- nanoping_api/_runtime.py +685 -0
- nanoping_api/py.typed +0 -0
- nanoping_api-11.1.0.dev0.dist-info/METADATA +63 -0
- nanoping_api-11.1.0.dev0.dist-info/RECORD +8 -0
- nanoping_api-11.1.0.dev0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,4182 @@
|
|
|
1
|
+
# Generated from the gRPC bridge protos and HTTP rules. Do not edit.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import dataclasses
|
|
6
|
+
import datetime
|
|
7
|
+
from collections.abc import Mapping, Sequence
|
|
8
|
+
|
|
9
|
+
from ._runtime import (
|
|
10
|
+
AsyncBidiStream,
|
|
11
|
+
AsyncServerStream,
|
|
12
|
+
AsyncTransport,
|
|
13
|
+
BidiStream,
|
|
14
|
+
ProtoEnum,
|
|
15
|
+
Route,
|
|
16
|
+
ServerStream,
|
|
17
|
+
Transport,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"Address",
|
|
22
|
+
"AsyncBlueprintsClient",
|
|
23
|
+
"AsyncConfigServiceClient",
|
|
24
|
+
"AsyncHubClientServiceClient",
|
|
25
|
+
"AsyncHubServerServiceClient",
|
|
26
|
+
"AsyncLoggingServiceClient",
|
|
27
|
+
"AsyncNetworkInstancesClient",
|
|
28
|
+
"AsyncNetworksClient",
|
|
29
|
+
"AsyncPipelinesServiceClient",
|
|
30
|
+
"AsyncResourcesServiceClient",
|
|
31
|
+
"AuthenticateByRequestRequest",
|
|
32
|
+
"AuthenticateByRequestResponse",
|
|
33
|
+
"AuthenticationByRequestAnswer",
|
|
34
|
+
"AuthenticationByRequestRequest",
|
|
35
|
+
"Blueprint",
|
|
36
|
+
"BlueprintWrite",
|
|
37
|
+
"BlueprintsClient",
|
|
38
|
+
"BoolMetric",
|
|
39
|
+
"Carrier",
|
|
40
|
+
"Collection",
|
|
41
|
+
"ConfigCompatability",
|
|
42
|
+
"ConfigServiceClient",
|
|
43
|
+
"ConnectionState",
|
|
44
|
+
"Constant",
|
|
45
|
+
"CreateBlueprintRequest",
|
|
46
|
+
"CreateBlueprintResponse",
|
|
47
|
+
"CreateNetworkRequest",
|
|
48
|
+
"CreateNetworkResponse",
|
|
49
|
+
"CreatePipelineRequest",
|
|
50
|
+
"CreatePipelineResponse",
|
|
51
|
+
"DefaultNetworkCarrier",
|
|
52
|
+
"DefaultNetworkCarrierAddress",
|
|
53
|
+
"DefaultNetworkCarriers",
|
|
54
|
+
"DeleteBlueprintRequest",
|
|
55
|
+
"DeleteBlueprintResponse",
|
|
56
|
+
"DeleteNetworkRequest",
|
|
57
|
+
"DeleteNetworkResponse",
|
|
58
|
+
"DeletePipelineRequest",
|
|
59
|
+
"DeletePipelineResponse",
|
|
60
|
+
"DisconnectRequest",
|
|
61
|
+
"DisconnectResponse",
|
|
62
|
+
"DownloadAppLogFileRequest",
|
|
63
|
+
"DownloadLogFileChunk",
|
|
64
|
+
"DownloadLogFileRequest",
|
|
65
|
+
"DownloadNetworkInstanceLogFileRequest",
|
|
66
|
+
"DownloadNetworkLogFileRequest",
|
|
67
|
+
"DownloadPipelineRunLogFileRequest",
|
|
68
|
+
"Enum8Metric",
|
|
69
|
+
"Enum8Metric_EnumValue",
|
|
70
|
+
"Float32Metric",
|
|
71
|
+
"Float64Metric",
|
|
72
|
+
"Flow",
|
|
73
|
+
"FlowsSample",
|
|
74
|
+
"GetBlueprintRequest",
|
|
75
|
+
"GetBlueprintResponse",
|
|
76
|
+
"GetBlueprintsRequest",
|
|
77
|
+
"GetBlueprintsResponse",
|
|
78
|
+
"GetDefaultNetworkCarriersRequest",
|
|
79
|
+
"GetDefaultNetworkCarriersResponse",
|
|
80
|
+
"GetLocalNodeIdRequest",
|
|
81
|
+
"GetLocalNodeIdResponse",
|
|
82
|
+
"GetNetworkInstancesRequest",
|
|
83
|
+
"GetNetworkInstancesResponse",
|
|
84
|
+
"GetNetworkPipelinesRequest",
|
|
85
|
+
"GetNetworkPipelinesResponse",
|
|
86
|
+
"GetNetworkRequest",
|
|
87
|
+
"GetNetworkResponse",
|
|
88
|
+
"GetNetworksRequest",
|
|
89
|
+
"GetNetworksResponse",
|
|
90
|
+
"GetNodeRequest",
|
|
91
|
+
"GetNodeResponse",
|
|
92
|
+
"GetNodesRequest",
|
|
93
|
+
"GetNodesResponse",
|
|
94
|
+
"GetPipelineByIdRequest",
|
|
95
|
+
"GetPipelineByIdResponse",
|
|
96
|
+
"GetPipelineByNameRequest",
|
|
97
|
+
"GetPipelineByNameResponse",
|
|
98
|
+
"GetPipelineByRunIdRequest",
|
|
99
|
+
"GetPipelineByRunIdResponse",
|
|
100
|
+
"GetPipelinesRequest",
|
|
101
|
+
"GetPipelinesResponse",
|
|
102
|
+
"HubClientServiceClient",
|
|
103
|
+
"HubNode",
|
|
104
|
+
"HubServerServiceClient",
|
|
105
|
+
"Int32Metric",
|
|
106
|
+
"Int64Metric",
|
|
107
|
+
"Kind",
|
|
108
|
+
"Kpi",
|
|
109
|
+
"Level",
|
|
110
|
+
"LogFileChunk",
|
|
111
|
+
"LogStreamMessages",
|
|
112
|
+
"LoggingOpenLogStreamRequest",
|
|
113
|
+
"LoggingOpenNetworkInstanceLogStreamRequest",
|
|
114
|
+
"LoggingOpenNetworkLogStreamRequest",
|
|
115
|
+
"LoggingServiceClient",
|
|
116
|
+
"Message",
|
|
117
|
+
"Messages",
|
|
118
|
+
"Metric",
|
|
119
|
+
"MetricsSample",
|
|
120
|
+
"Network",
|
|
121
|
+
"NetworkBlueprints",
|
|
122
|
+
"NetworkInstance",
|
|
123
|
+
"NetworkInstanceLogStreamMessages",
|
|
124
|
+
"NetworkInstancesClient",
|
|
125
|
+
"NetworkLogStreamMessages",
|
|
126
|
+
"NetworkPipeline",
|
|
127
|
+
"NetworksClient",
|
|
128
|
+
"NetworksNode",
|
|
129
|
+
"NetworksOpenNetworkInstanceLogStreamRequest",
|
|
130
|
+
"NetworksOpenNetworkLogStreamRequest",
|
|
131
|
+
"NodeMetadata",
|
|
132
|
+
"NodeMetadataItem",
|
|
133
|
+
"NodeService",
|
|
134
|
+
"NodeType",
|
|
135
|
+
"OpenAppLogStreamRequest",
|
|
136
|
+
"OpenFlowsStreamRequest",
|
|
137
|
+
"OpenMetricsStreamRequest",
|
|
138
|
+
"OpenPipelineRunLogStreamRequest",
|
|
139
|
+
"OpenTelemetryStreamRequest",
|
|
140
|
+
"Options",
|
|
141
|
+
"Pipeline",
|
|
142
|
+
"PipelineOpenLogStreamRequest",
|
|
143
|
+
"PipelinesServiceClient",
|
|
144
|
+
"RemoveNodeRequest",
|
|
145
|
+
"RemoveNodeResponse",
|
|
146
|
+
"ResourcesServiceClient",
|
|
147
|
+
"RestartPolicy",
|
|
148
|
+
"RestartPolicyAlways",
|
|
149
|
+
"RestartPolicyNever",
|
|
150
|
+
"RestartPolicyOnFailure",
|
|
151
|
+
"SetDefaultNetworkCarriersRequest",
|
|
152
|
+
"SetDefaultNetworkCarriersResponse",
|
|
153
|
+
"SetNodeRequest",
|
|
154
|
+
"SetNodeResponse",
|
|
155
|
+
"StartPipelineRequest",
|
|
156
|
+
"StartPipelineResponse",
|
|
157
|
+
"StartupPolicy",
|
|
158
|
+
"StartupPolicyAuto",
|
|
159
|
+
"StartupPolicyManual",
|
|
160
|
+
"StopPipelineRequest",
|
|
161
|
+
"StopPipelineResponse",
|
|
162
|
+
"StreamConnectionStateRequest",
|
|
163
|
+
"StreamConnectionStateResponse",
|
|
164
|
+
"StreamNetworkInstanceCreateEvent",
|
|
165
|
+
"StreamNetworkInstanceDeleteEvent",
|
|
166
|
+
"StreamNetworkInstanceEvent",
|
|
167
|
+
"StreamNetworkInstanceUpdateEvent",
|
|
168
|
+
"StreamNetworkInstancesRequest",
|
|
169
|
+
"StreamNetworkPipelineCreateEvent",
|
|
170
|
+
"StreamNetworkPipelineDeleteEvent",
|
|
171
|
+
"StreamNetworkPipelineEvent",
|
|
172
|
+
"StreamNetworkPipelineUpdateEvent",
|
|
173
|
+
"StreamNetworkPipelinesRequest",
|
|
174
|
+
"StreamNetworksCreateEvent",
|
|
175
|
+
"StreamNetworksDeleteEvent",
|
|
176
|
+
"StreamNetworksEvent",
|
|
177
|
+
"StreamNetworksRequest",
|
|
178
|
+
"StreamNetworksUpdateEvent",
|
|
179
|
+
"StreamNodesInitialResponse",
|
|
180
|
+
"StreamNodesResponse",
|
|
181
|
+
"StreamNodesUpdateResponse",
|
|
182
|
+
"StreamPipelinesCreateEvent",
|
|
183
|
+
"StreamPipelinesDeleteEvent",
|
|
184
|
+
"StreamPipelinesEvent",
|
|
185
|
+
"StreamPipelinesRequest",
|
|
186
|
+
"StreamPipelinesUpdateEvent",
|
|
187
|
+
"TelemetrySample",
|
|
188
|
+
"ToggleNetworkPipelineRequest",
|
|
189
|
+
"ToggleNetworkPipelineResponse",
|
|
190
|
+
"UInt32Metric",
|
|
191
|
+
"UInt64Metric",
|
|
192
|
+
"UpdateBlueprintRequest",
|
|
193
|
+
"UpdateBlueprintResponse",
|
|
194
|
+
"UpdateNetworkRequest",
|
|
195
|
+
"UpdateNetworkResponse",
|
|
196
|
+
"UpdatePipelineRequest",
|
|
197
|
+
"UpdatePipelineResponse",
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class ConnectionState(ProtoEnum):
|
|
202
|
+
"""Connection state between a node and its hub server."""
|
|
203
|
+
|
|
204
|
+
UNAUTHENTICATED = "UNAUTHENTICATED"
|
|
205
|
+
"""The node is not authenticated with a hub server."""
|
|
206
|
+
DISCONNECTED = "DISCONNECTED"
|
|
207
|
+
"""The node is authenticated but not connected to the hub server."""
|
|
208
|
+
CONNECTED = "CONNECTED"
|
|
209
|
+
"""The node is connected to the hub server."""
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class NodeService(ProtoEnum):
|
|
213
|
+
"""Services a node can offer."""
|
|
214
|
+
|
|
215
|
+
HUB_SERVER = "HUB_SERVER"
|
|
216
|
+
"""The node hosts a hub server."""
|
|
217
|
+
RESOURCES = "RESOURCES"
|
|
218
|
+
"""The node offers resources."""
|
|
219
|
+
LOGGING = "LOGGING"
|
|
220
|
+
"""The node offers logging."""
|
|
221
|
+
PIPELINES = "PIPELINES"
|
|
222
|
+
"""The node can run pipelines."""
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class Level(ProtoEnum):
|
|
226
|
+
"""Severity of a log message, from the most verbose to the most severe."""
|
|
227
|
+
|
|
228
|
+
STATE = "STATE"
|
|
229
|
+
"""State information, the most verbose level."""
|
|
230
|
+
DEBUG = "DEBUG"
|
|
231
|
+
"""Debugging details."""
|
|
232
|
+
INFO = "INFO"
|
|
233
|
+
"""General information."""
|
|
234
|
+
WARNING = "WARNING"
|
|
235
|
+
"""Something unexpected that did not stop the operation."""
|
|
236
|
+
ERROR = "ERROR"
|
|
237
|
+
"""An operation failed."""
|
|
238
|
+
FATAL = "FATAL"
|
|
239
|
+
"""A failure the process could not recover from."""
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class Kind(ProtoEnum):
|
|
243
|
+
"""How the value of a metric changes over time."""
|
|
244
|
+
|
|
245
|
+
GAUGE = "GAUGE"
|
|
246
|
+
"""The value can both increase and decrease, for example memory in use."""
|
|
247
|
+
COUNTER = "COUNTER"
|
|
248
|
+
"""The value can only increase, for example a total byte count."""
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class NodeType(ProtoEnum):
|
|
252
|
+
"""The role of a node in a network."""
|
|
253
|
+
|
|
254
|
+
NODE_TYPE_CLIENT = "NODE_TYPE_CLIENT"
|
|
255
|
+
"""A client node."""
|
|
256
|
+
NODE_TYPE_RELAY = "NODE_TYPE_RELAY"
|
|
257
|
+
"""The relay node, named by the network's `relay_node_id`."""
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class ConfigCompatability(ProtoEnum):
|
|
261
|
+
"""Whether the node can run a pipeline configuration."""
|
|
262
|
+
|
|
263
|
+
COMPATIBLE = "COMPATIBLE"
|
|
264
|
+
"""The node can run the configuration."""
|
|
265
|
+
INCOMPATIBLE = "INCOMPATIBLE"
|
|
266
|
+
"""The configuration was made for a newer NanoPing version than the one running on
|
|
267
|
+
the node.
|
|
268
|
+
"""
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@dataclasses.dataclass(kw_only=True)
|
|
272
|
+
class AuthenticateByRequestRequest:
|
|
273
|
+
"""Request for authenticateByRequest."""
|
|
274
|
+
|
|
275
|
+
hub_server_address: str = ""
|
|
276
|
+
"""HTTP or HTTPS address of the hub server. Example: `http://127.0.0.1:8769`"""
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
@dataclasses.dataclass(kw_only=True)
|
|
280
|
+
class AuthenticateByRequestResponse:
|
|
281
|
+
"""Response for authenticateByRequest. Empty on success."""
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@dataclasses.dataclass(kw_only=True)
|
|
285
|
+
class AuthenticationByRequestAnswer:
|
|
286
|
+
"""An answer to an authentication by request, sent by the caller."""
|
|
287
|
+
|
|
288
|
+
request_id: int = 0
|
|
289
|
+
"""Id of the request being answered, as received in the request."""
|
|
290
|
+
accept: bool = False
|
|
291
|
+
"""True to accept the request, false to reject it."""
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@dataclasses.dataclass(kw_only=True)
|
|
295
|
+
class AuthenticationByRequestRequest:
|
|
296
|
+
"""An authentication by request from a node that wants to authenticate with the hub
|
|
297
|
+
server.
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
node: HubNode = dataclasses.field(default_factory=lambda: HubNode())
|
|
301
|
+
"""Information about the node asking to authenticate."""
|
|
302
|
+
request_id: int = 0
|
|
303
|
+
"""Id of the request, used when answering it."""
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
@dataclasses.dataclass(kw_only=True)
|
|
307
|
+
class DefaultNetworkCarrier:
|
|
308
|
+
"""A carrier a node receives every time it joins a new network. Every setting is
|
|
309
|
+
optional.
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
address: DefaultNetworkCarrierAddress | None = None
|
|
313
|
+
"""Address the carrier uses."""
|
|
314
|
+
interface: str | None = None
|
|
315
|
+
"""Name of the network interface the carrier uses. Example: `eth0`"""
|
|
316
|
+
bandwidth_priority: int | None = None
|
|
317
|
+
"""Bandwidth priority of the carrier. Example: `100`"""
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
@dataclasses.dataclass(kw_only=True)
|
|
321
|
+
class DefaultNetworkCarrierAddress:
|
|
322
|
+
"""Address of a default network carrier."""
|
|
323
|
+
|
|
324
|
+
ip: str = ""
|
|
325
|
+
"""IP address of the carrier. Example: `192.168.1.20`"""
|
|
326
|
+
port: int = 0
|
|
327
|
+
"""Port of the carrier. Example: `3425`"""
|
|
328
|
+
external_ip: str | None = None
|
|
329
|
+
"""IP address the carrier is reachable at from outside, for example behind NAT.
|
|
330
|
+
Example: `203.0.113.10`
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@dataclasses.dataclass(kw_only=True)
|
|
335
|
+
class DefaultNetworkCarriers:
|
|
336
|
+
"""A list of default network carriers."""
|
|
337
|
+
|
|
338
|
+
carriers: list[DefaultNetworkCarrier] = dataclasses.field(default_factory=list)
|
|
339
|
+
"""The default network carriers."""
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@dataclasses.dataclass(kw_only=True)
|
|
343
|
+
class DisconnectRequest:
|
|
344
|
+
"""Request for disconnect."""
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@dataclasses.dataclass(kw_only=True)
|
|
348
|
+
class DisconnectResponse:
|
|
349
|
+
"""Response for disconnect."""
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@dataclasses.dataclass(kw_only=True)
|
|
353
|
+
class GetDefaultNetworkCarriersRequest:
|
|
354
|
+
"""Request for getDefaultNetworkCarriers."""
|
|
355
|
+
|
|
356
|
+
node_id: str = ""
|
|
357
|
+
"""Id of the node to read the default network carriers from."""
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
@dataclasses.dataclass(kw_only=True)
|
|
361
|
+
class GetDefaultNetworkCarriersResponse:
|
|
362
|
+
"""Response for getDefaultNetworkCarriers."""
|
|
363
|
+
|
|
364
|
+
carriers: list[DefaultNetworkCarrier] = dataclasses.field(default_factory=list)
|
|
365
|
+
"""The default network carriers of the node. Empty when none are configured."""
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
@dataclasses.dataclass(kw_only=True)
|
|
369
|
+
class GetLocalNodeIdRequest:
|
|
370
|
+
"""Request for getLocalNodeId."""
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
@dataclasses.dataclass(kw_only=True)
|
|
374
|
+
class GetLocalNodeIdResponse:
|
|
375
|
+
"""Response for getLocalNodeId."""
|
|
376
|
+
|
|
377
|
+
node_id: str = ""
|
|
378
|
+
"""Id of the node hosting the API."""
|
|
379
|
+
is_authenticated: bool = False
|
|
380
|
+
"""True if the node holds a sign-in to a hub server. It may still be disconnected
|
|
381
|
+
from it at the moment.
|
|
382
|
+
"""
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
@dataclasses.dataclass(kw_only=True)
|
|
386
|
+
class GetNodeRequest:
|
|
387
|
+
"""Request for getNode."""
|
|
388
|
+
|
|
389
|
+
node_id: str = ""
|
|
390
|
+
"""Id of the node to get information about, for example the id returned by
|
|
391
|
+
getLocalNodeId.
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
@dataclasses.dataclass(kw_only=True)
|
|
396
|
+
class GetNodeResponse:
|
|
397
|
+
"""Response for getNode."""
|
|
398
|
+
|
|
399
|
+
node: HubNode = dataclasses.field(default_factory=lambda: HubNode())
|
|
400
|
+
"""Information about the node."""
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@dataclasses.dataclass(kw_only=True)
|
|
404
|
+
class GetNodesRequest:
|
|
405
|
+
"""Filters for listing the nodes of the hub server. All given filters must match for
|
|
406
|
+
a node to be included.
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
metadata_filters: dict[str, NodeMetadataItem] = dataclasses.field(default_factory=dict)
|
|
410
|
+
"""Metadata filters keyed by metadata key. A node is included only if it has every
|
|
411
|
+
key with an equal value of the same type. Leave empty to not filter by metadata.
|
|
412
|
+
"""
|
|
413
|
+
service_filters: list[NodeService] = dataclasses.field(default_factory=list)
|
|
414
|
+
"""Service filters. A node is included only if it offers every listed service. Leave
|
|
415
|
+
empty to not filter by service.
|
|
416
|
+
"""
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@dataclasses.dataclass(kw_only=True)
|
|
420
|
+
class GetNodesResponse:
|
|
421
|
+
"""Response for getNodes."""
|
|
422
|
+
|
|
423
|
+
nodes: list[HubNode] = dataclasses.field(default_factory=list)
|
|
424
|
+
"""The nodes matching the filters."""
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@dataclasses.dataclass(kw_only=True)
|
|
428
|
+
class HubNode:
|
|
429
|
+
"""Information about a node."""
|
|
430
|
+
|
|
431
|
+
id: str = ""
|
|
432
|
+
"""Unique id of the node."""
|
|
433
|
+
name: str = ""
|
|
434
|
+
"""Human readable name of the node."""
|
|
435
|
+
online: bool = False
|
|
436
|
+
"""Whether the node is currently online and connected to the hub server."""
|
|
437
|
+
services: list[NodeService] = dataclasses.field(default_factory=list)
|
|
438
|
+
"""Services offered by the node."""
|
|
439
|
+
metadata: NodeMetadata = dataclasses.field(default_factory=lambda: NodeMetadata())
|
|
440
|
+
"""Metadata of the node."""
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
@dataclasses.dataclass(kw_only=True)
|
|
444
|
+
class NodeMetadata:
|
|
445
|
+
"""User defined key/value metadata attached to a node."""
|
|
446
|
+
|
|
447
|
+
items: dict[str, NodeMetadataItem] = dataclasses.field(default_factory=dict)
|
|
448
|
+
"""Metadata items keyed by name."""
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
@dataclasses.dataclass(kw_only=True)
|
|
452
|
+
class NodeMetadataItem:
|
|
453
|
+
"""A single metadata value of a node. Set exactly one of the value fields."""
|
|
454
|
+
|
|
455
|
+
bytes_value: bytes | None = None
|
|
456
|
+
"""Raw bytes value."""
|
|
457
|
+
string_value: str | None = None
|
|
458
|
+
"""Text value."""
|
|
459
|
+
int_value: int | None = None
|
|
460
|
+
"""Signed 64-bit integer value."""
|
|
461
|
+
uint_value: int | None = None
|
|
462
|
+
"""Unsigned 64-bit integer value."""
|
|
463
|
+
double_value: float | None = None
|
|
464
|
+
"""64-bit floating point value."""
|
|
465
|
+
float_value: float | None = None
|
|
466
|
+
"""32-bit floating point value."""
|
|
467
|
+
bool_value: bool | None = None
|
|
468
|
+
"""Boolean value."""
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
@dataclasses.dataclass(kw_only=True)
|
|
472
|
+
class RemoveNodeRequest:
|
|
473
|
+
"""Request for removeNode."""
|
|
474
|
+
|
|
475
|
+
node_id: str = ""
|
|
476
|
+
"""Id of the node to remove."""
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
@dataclasses.dataclass(kw_only=True)
|
|
480
|
+
class RemoveNodeResponse:
|
|
481
|
+
"""Response for removeNode."""
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
@dataclasses.dataclass(kw_only=True)
|
|
485
|
+
class SetDefaultNetworkCarriersRequest:
|
|
486
|
+
"""Request for setDefaultNetworkCarriers."""
|
|
487
|
+
|
|
488
|
+
node_id: str = ""
|
|
489
|
+
"""Id of the node to set the default network carriers on."""
|
|
490
|
+
carriers: DefaultNetworkCarriers | None = None
|
|
491
|
+
"""The new default network carriers, replacing the current ones. Leave unset to
|
|
492
|
+
remove all default carriers.
|
|
493
|
+
"""
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
@dataclasses.dataclass(kw_only=True)
|
|
497
|
+
class SetDefaultNetworkCarriersResponse:
|
|
498
|
+
"""Response for setDefaultNetworkCarriers."""
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
@dataclasses.dataclass(kw_only=True)
|
|
502
|
+
class SetNodeRequest:
|
|
503
|
+
"""Request for setNode."""
|
|
504
|
+
|
|
505
|
+
node_id: str = ""
|
|
506
|
+
"""Id of the node to change."""
|
|
507
|
+
name: str = ""
|
|
508
|
+
"""New name of the node. Example: `edge-node-1`"""
|
|
509
|
+
metadata: NodeMetadata = dataclasses.field(default_factory=lambda: NodeMetadata())
|
|
510
|
+
"""New metadata of the node. Replaces all existing metadata, so leaving it empty
|
|
511
|
+
removes the metadata.
|
|
512
|
+
"""
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
@dataclasses.dataclass(kw_only=True)
|
|
516
|
+
class SetNodeResponse:
|
|
517
|
+
"""Response for setNode."""
|
|
518
|
+
|
|
519
|
+
node: HubNode = dataclasses.field(default_factory=lambda: HubNode())
|
|
520
|
+
"""The node information after the change."""
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
@dataclasses.dataclass(kw_only=True)
|
|
524
|
+
class StreamConnectionStateRequest:
|
|
525
|
+
"""Request for streamConnectionState."""
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
@dataclasses.dataclass(kw_only=True)
|
|
529
|
+
class StreamConnectionStateResponse:
|
|
530
|
+
"""A connection state update."""
|
|
531
|
+
|
|
532
|
+
state: ConnectionState = ConnectionState.UNAUTHENTICATED
|
|
533
|
+
"""The current connection state."""
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
@dataclasses.dataclass(kw_only=True)
|
|
537
|
+
class StreamNodesInitialResponse:
|
|
538
|
+
"""The nodes of the hub server when the stream opened."""
|
|
539
|
+
|
|
540
|
+
nodes: list[HubNode] = dataclasses.field(default_factory=list)
|
|
541
|
+
"""The nodes matching the filters."""
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
@dataclasses.dataclass(kw_only=True)
|
|
545
|
+
class StreamNodesResponse:
|
|
546
|
+
"""A message on the streamNodes stream."""
|
|
547
|
+
|
|
548
|
+
initial_response: StreamNodesInitialResponse | None = None
|
|
549
|
+
"""Sent once as the first message, with the nodes matching the filters when the
|
|
550
|
+
stream opened.
|
|
551
|
+
"""
|
|
552
|
+
update_response: StreamNodesUpdateResponse | None = None
|
|
553
|
+
"""Sent for every later change to a node."""
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
@dataclasses.dataclass(kw_only=True)
|
|
557
|
+
class StreamNodesUpdateResponse:
|
|
558
|
+
"""A change to a single node. Exactly one field is set, telling what changed."""
|
|
559
|
+
|
|
560
|
+
connected_node: HubNode | None = None
|
|
561
|
+
"""The node connected to the hub server."""
|
|
562
|
+
disconnected_node: HubNode | None = None
|
|
563
|
+
"""The node disconnected from the hub server."""
|
|
564
|
+
authenticated_node: HubNode | None = None
|
|
565
|
+
"""The node was authenticated with the hub server."""
|
|
566
|
+
deauthenticated_node: HubNode | None = None
|
|
567
|
+
"""The node was deauthenticated and removed from the hub server."""
|
|
568
|
+
updated_metadata_node: HubNode | None = None
|
|
569
|
+
"""The node's metadata changed."""
|
|
570
|
+
updated_name_node: HubNode | None = None
|
|
571
|
+
"""The node's name changed."""
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
@dataclasses.dataclass(kw_only=True)
|
|
575
|
+
class DownloadAppLogFileRequest:
|
|
576
|
+
"""Selects the node's application log file. Takes no parameters."""
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
@dataclasses.dataclass(kw_only=True)
|
|
580
|
+
class DownloadLogFileChunk:
|
|
581
|
+
"""One message of a log file download: either a piece of the file or an error."""
|
|
582
|
+
|
|
583
|
+
error: str | None = None
|
|
584
|
+
"""Why the file could not be read, for example because it does not exist. No more
|
|
585
|
+
chunks follow.
|
|
586
|
+
"""
|
|
587
|
+
file_chunk: LogFileChunk | None = None
|
|
588
|
+
"""The next piece of the file."""
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
@dataclasses.dataclass(kw_only=True)
|
|
592
|
+
class DownloadLogFileRequest:
|
|
593
|
+
"""Downloads one log file from a node."""
|
|
594
|
+
|
|
595
|
+
node_id: str = ""
|
|
596
|
+
"""ID of the node that holds the log file."""
|
|
597
|
+
app_log_file_request: DownloadAppLogFileRequest | None = None
|
|
598
|
+
"""Download the node's application log."""
|
|
599
|
+
pipeline_run_log_file_request: DownloadPipelineRunLogFileRequest | None = None
|
|
600
|
+
"""Download the log of a pipeline run."""
|
|
601
|
+
network_log_file_request: DownloadNetworkLogFileRequest | None = None
|
|
602
|
+
"""Download the log of a network."""
|
|
603
|
+
network_instance_log_file_request: DownloadNetworkInstanceLogFileRequest | None = None
|
|
604
|
+
"""Download the log of a network instance."""
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
@dataclasses.dataclass(kw_only=True)
|
|
608
|
+
class DownloadNetworkInstanceLogFileRequest:
|
|
609
|
+
"""Selects the log file of a network instance."""
|
|
610
|
+
|
|
611
|
+
network_instance_id: str = ""
|
|
612
|
+
"""ID of the network instance. Must not be empty."""
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
@dataclasses.dataclass(kw_only=True)
|
|
616
|
+
class DownloadNetworkLogFileRequest:
|
|
617
|
+
"""Selects the log file of a network."""
|
|
618
|
+
|
|
619
|
+
network_id: str = ""
|
|
620
|
+
"""ID of the network. Must not be empty."""
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
@dataclasses.dataclass(kw_only=True)
|
|
624
|
+
class DownloadPipelineRunLogFileRequest:
|
|
625
|
+
"""Selects the log file of a pipeline run."""
|
|
626
|
+
|
|
627
|
+
pipeline_run_id: str = ""
|
|
628
|
+
"""ID of the pipeline run. Must not be empty."""
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
@dataclasses.dataclass(kw_only=True)
|
|
632
|
+
class LogFileChunk:
|
|
633
|
+
"""A piece of a log file."""
|
|
634
|
+
|
|
635
|
+
content: bytes = b""
|
|
636
|
+
"""Raw file bytes, up to 64 KiB per chunk."""
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
@dataclasses.dataclass(kw_only=True)
|
|
640
|
+
class Message:
|
|
641
|
+
"""A single log entry."""
|
|
642
|
+
|
|
643
|
+
timestamp: datetime.datetime | None = None
|
|
644
|
+
"""When the entry was logged."""
|
|
645
|
+
level: Level = Level.STATE
|
|
646
|
+
"""Severity of the entry."""
|
|
647
|
+
message: str = ""
|
|
648
|
+
"""The log text. Holds the whole raw line when no message could be extracted from
|
|
649
|
+
it.
|
|
650
|
+
"""
|
|
651
|
+
data: str = ""
|
|
652
|
+
"""The raw log line when it is valid JSON, so structured fields can be read from it.
|
|
653
|
+
Empty otherwise.
|
|
654
|
+
"""
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
@dataclasses.dataclass(kw_only=True)
|
|
658
|
+
class Messages:
|
|
659
|
+
"""A batch of log entries, oldest first."""
|
|
660
|
+
|
|
661
|
+
messages: list[Message] = dataclasses.field(default_factory=list)
|
|
662
|
+
"""The log entries."""
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
@dataclasses.dataclass(kw_only=True)
|
|
666
|
+
class OpenAppLogStreamRequest:
|
|
667
|
+
"""Selects the node's application log. Takes no parameters."""
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
@dataclasses.dataclass(kw_only=True)
|
|
671
|
+
class LoggingOpenLogStreamRequest:
|
|
672
|
+
"""Opens a stream of log messages from one log on a node."""
|
|
673
|
+
|
|
674
|
+
node_id: str = ""
|
|
675
|
+
"""ID of the node whose log to stream."""
|
|
676
|
+
options: Options = dataclasses.field(default_factory=lambda: Options())
|
|
677
|
+
"""Stream options. When unset, only new entries are sent."""
|
|
678
|
+
app_log_stream_request: OpenAppLogStreamRequest | None = None
|
|
679
|
+
"""Stream the node's application log."""
|
|
680
|
+
pipeline_run_log_stream_request: OpenPipelineRunLogStreamRequest | None = None
|
|
681
|
+
"""Stream the log of a pipeline run."""
|
|
682
|
+
network_log_stream_request: LoggingOpenNetworkLogStreamRequest | None = None
|
|
683
|
+
"""Stream the log of a network."""
|
|
684
|
+
network_instance_log_stream_request: LoggingOpenNetworkInstanceLogStreamRequest | None = None
|
|
685
|
+
"""Stream the log of a network instance."""
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
@dataclasses.dataclass(kw_only=True)
|
|
689
|
+
class LoggingOpenNetworkInstanceLogStreamRequest:
|
|
690
|
+
"""Selects the log of a network instance."""
|
|
691
|
+
|
|
692
|
+
network_instance_id: str = ""
|
|
693
|
+
"""ID of the network instance. Must not be empty."""
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
@dataclasses.dataclass(kw_only=True)
|
|
697
|
+
class LoggingOpenNetworkLogStreamRequest:
|
|
698
|
+
"""Selects the log of a network."""
|
|
699
|
+
|
|
700
|
+
network_id: str = ""
|
|
701
|
+
"""ID of the network. Must not be empty."""
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
@dataclasses.dataclass(kw_only=True)
|
|
705
|
+
class OpenPipelineRunLogStreamRequest:
|
|
706
|
+
"""Selects the log of a pipeline run."""
|
|
707
|
+
|
|
708
|
+
pipeline_run_id: str = ""
|
|
709
|
+
"""ID of the pipeline run. Must not be empty."""
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
@dataclasses.dataclass(kw_only=True)
|
|
713
|
+
class Options:
|
|
714
|
+
"""Options for opening a log stream."""
|
|
715
|
+
|
|
716
|
+
lines: int | None = None
|
|
717
|
+
"""The number of entries."""
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
@dataclasses.dataclass(kw_only=True)
|
|
721
|
+
class BoolMetric:
|
|
722
|
+
"""A metric holding a true or false value."""
|
|
723
|
+
|
|
724
|
+
value: bool | None = None
|
|
725
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
726
|
+
description: str = ""
|
|
727
|
+
"""Human-readable description of what the metric measures."""
|
|
728
|
+
unit: str | None = None
|
|
729
|
+
"""The unit. Unset when the value has no unit."""
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
@dataclasses.dataclass(kw_only=True)
|
|
733
|
+
class Collection:
|
|
734
|
+
"""A group of related metrics, such as the memory metrics of a node."""
|
|
735
|
+
|
|
736
|
+
path: str = ""
|
|
737
|
+
"""Path identifying the collection, for example `/system/memory`."""
|
|
738
|
+
metrics: dict[str, Metric] = dataclasses.field(default_factory=dict)
|
|
739
|
+
"""The metrics in the collection, keyed by metric name."""
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
@dataclasses.dataclass(kw_only=True)
|
|
743
|
+
class Constant:
|
|
744
|
+
"""A metric whose value never changes, such as the CPU architecture."""
|
|
745
|
+
|
|
746
|
+
uint64: int | None = None
|
|
747
|
+
"""An unsigned integer value."""
|
|
748
|
+
int64: int | None = None
|
|
749
|
+
"""A signed integer value."""
|
|
750
|
+
float64: float | None = None
|
|
751
|
+
"""A floating-point value."""
|
|
752
|
+
boolean: bool | None = None
|
|
753
|
+
"""A true or false value."""
|
|
754
|
+
string: str | None = None
|
|
755
|
+
"""A text value."""
|
|
756
|
+
description: str = ""
|
|
757
|
+
"""Human-readable description of what the constant describes."""
|
|
758
|
+
unit: str | None = None
|
|
759
|
+
"""The unit. Unset when the value has no unit."""
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
@dataclasses.dataclass(kw_only=True)
|
|
763
|
+
class Enum8Metric:
|
|
764
|
+
"""A metric holding one value out of a fixed set of named values."""
|
|
765
|
+
|
|
766
|
+
value: int | None = None
|
|
767
|
+
"""The index. Unset when the metric has no value in this sample."""
|
|
768
|
+
description: str = ""
|
|
769
|
+
"""Human-readable description of what the metric measures."""
|
|
770
|
+
values: dict[int, Enum8Metric_EnumValue] = dataclasses.field(default_factory=dict)
|
|
771
|
+
"""The values the metric can take, keyed by index."""
|
|
772
|
+
unit: str | None = None
|
|
773
|
+
"""The unit. Unset when the value has no unit."""
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
@dataclasses.dataclass(kw_only=True)
|
|
777
|
+
class Enum8Metric_EnumValue:
|
|
778
|
+
"""A named value the metric can take."""
|
|
779
|
+
|
|
780
|
+
name: str = ""
|
|
781
|
+
"""Name of the value."""
|
|
782
|
+
description: str | None = None
|
|
783
|
+
"""The description."""
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
@dataclasses.dataclass(kw_only=True)
|
|
787
|
+
class Float32Metric:
|
|
788
|
+
"""A metric holding a 32-bit floating-point value."""
|
|
789
|
+
|
|
790
|
+
value: float | None = None
|
|
791
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
792
|
+
description: str = ""
|
|
793
|
+
"""Human-readable description of what the metric measures."""
|
|
794
|
+
kind: Kind = Kind.GAUGE
|
|
795
|
+
"""Whether the value can only increase or can also decrease."""
|
|
796
|
+
unit: str | None = None
|
|
797
|
+
"""The unit, for example `bytes` or `percent`. Unset when the value has no unit."""
|
|
798
|
+
min: float | None = None
|
|
799
|
+
"""The minimum. Unset when there is no known lower bound."""
|
|
800
|
+
max: float | None = None
|
|
801
|
+
"""The maximum. Unset when there is no known upper bound."""
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
@dataclasses.dataclass(kw_only=True)
|
|
805
|
+
class Float64Metric:
|
|
806
|
+
"""A metric holding a 64-bit floating-point value."""
|
|
807
|
+
|
|
808
|
+
value: float | None = None
|
|
809
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
810
|
+
description: str = ""
|
|
811
|
+
"""Human-readable description of what the metric measures."""
|
|
812
|
+
kind: Kind = Kind.GAUGE
|
|
813
|
+
"""Whether the value can only increase or can also decrease."""
|
|
814
|
+
unit: str | None = None
|
|
815
|
+
"""The unit, for example `bytes` or `percent`. Unset when the value has no unit."""
|
|
816
|
+
min: float | None = None
|
|
817
|
+
"""The minimum. Unset when there is no known lower bound."""
|
|
818
|
+
max: float | None = None
|
|
819
|
+
"""The maximum. Unset when there is no known upper bound."""
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
@dataclasses.dataclass(kw_only=True)
|
|
823
|
+
class Int32Metric:
|
|
824
|
+
"""A metric holding a signed 32-bit integer value."""
|
|
825
|
+
|
|
826
|
+
value: int | None = None
|
|
827
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
828
|
+
description: str = ""
|
|
829
|
+
"""Human-readable description of what the metric measures."""
|
|
830
|
+
kind: Kind = Kind.GAUGE
|
|
831
|
+
"""Whether the value can only increase or can also decrease."""
|
|
832
|
+
unit: str | None = None
|
|
833
|
+
"""The unit, for example `bytes` or `percent`. Unset when the value has no unit."""
|
|
834
|
+
min: int | None = None
|
|
835
|
+
"""The minimum. Unset when there is no known lower bound."""
|
|
836
|
+
max: int | None = None
|
|
837
|
+
"""The maximum. Unset when there is no known upper bound."""
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
@dataclasses.dataclass(kw_only=True)
|
|
841
|
+
class Int64Metric:
|
|
842
|
+
"""A metric holding a signed 64-bit integer value."""
|
|
843
|
+
|
|
844
|
+
value: int | None = None
|
|
845
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
846
|
+
description: str = ""
|
|
847
|
+
"""Human-readable description of what the metric measures."""
|
|
848
|
+
kind: Kind = Kind.GAUGE
|
|
849
|
+
"""Whether the value can only increase or can also decrease."""
|
|
850
|
+
unit: str | None = None
|
|
851
|
+
"""The unit, for example `bytes` or `percent`. Unset when the value has no unit."""
|
|
852
|
+
min: int | None = None
|
|
853
|
+
"""The minimum. Unset when there is no known lower bound."""
|
|
854
|
+
max: int | None = None
|
|
855
|
+
"""The maximum. Unset when there is no known upper bound."""
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
@dataclasses.dataclass(kw_only=True)
|
|
859
|
+
class Metric:
|
|
860
|
+
"""A single metric. Exactly one of the fields is set, depending on the metric's
|
|
861
|
+
type.
|
|
862
|
+
"""
|
|
863
|
+
|
|
864
|
+
constant: Constant | None = None
|
|
865
|
+
"""A metric with a fixed value."""
|
|
866
|
+
uint64: UInt64Metric | None = None
|
|
867
|
+
"""An unsigned 64-bit integer metric."""
|
|
868
|
+
int64: Int64Metric | None = None
|
|
869
|
+
"""A signed 64-bit integer metric."""
|
|
870
|
+
uint32: UInt32Metric | None = None
|
|
871
|
+
"""An unsigned 32-bit integer metric."""
|
|
872
|
+
int32: Int32Metric | None = None
|
|
873
|
+
"""A signed 32-bit integer metric."""
|
|
874
|
+
float64: Float64Metric | None = None
|
|
875
|
+
"""A 64-bit floating-point metric."""
|
|
876
|
+
float32: Float32Metric | None = None
|
|
877
|
+
"""A 32-bit floating-point metric."""
|
|
878
|
+
boolean: BoolMetric | None = None
|
|
879
|
+
"""A true or false metric."""
|
|
880
|
+
enum8: Enum8Metric | None = None
|
|
881
|
+
"""A metric with one of a fixed set of named values."""
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
@dataclasses.dataclass(kw_only=True)
|
|
885
|
+
class UInt32Metric:
|
|
886
|
+
"""A metric holding an unsigned 32-bit integer value."""
|
|
887
|
+
|
|
888
|
+
value: int | None = None
|
|
889
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
890
|
+
description: str = ""
|
|
891
|
+
"""Human-readable description of what the metric measures."""
|
|
892
|
+
kind: Kind = Kind.GAUGE
|
|
893
|
+
"""Whether the value can only increase or can also decrease."""
|
|
894
|
+
unit: str | None = None
|
|
895
|
+
"""The unit, for example `bytes` or `percent`. Unset when the value has no unit."""
|
|
896
|
+
min: int | None = None
|
|
897
|
+
"""The minimum. Unset when there is no known lower bound."""
|
|
898
|
+
max: int | None = None
|
|
899
|
+
"""The maximum. Unset when there is no known upper bound."""
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
@dataclasses.dataclass(kw_only=True)
|
|
903
|
+
class UInt64Metric:
|
|
904
|
+
"""A metric holding an unsigned 64-bit integer value."""
|
|
905
|
+
|
|
906
|
+
value: int | None = None
|
|
907
|
+
"""The value. Unset when the metric has no value in this sample."""
|
|
908
|
+
description: str = ""
|
|
909
|
+
"""Human-readable description of what the metric measures."""
|
|
910
|
+
kind: Kind = Kind.GAUGE
|
|
911
|
+
"""Whether the value can only increase or can also decrease."""
|
|
912
|
+
unit: str | None = None
|
|
913
|
+
"""The unit, for example `bytes` or `percent`. Unset when the value has no unit."""
|
|
914
|
+
min: int | None = None
|
|
915
|
+
"""The minimum. Unset when there is no known lower bound."""
|
|
916
|
+
max: int | None = None
|
|
917
|
+
"""The maximum. Unset when there is no known upper bound."""
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
@dataclasses.dataclass(kw_only=True)
|
|
921
|
+
class Address:
|
|
922
|
+
"""The address of a carrier."""
|
|
923
|
+
|
|
924
|
+
ip: str = ""
|
|
925
|
+
"""The IP address. Example: `192.168.1.20`"""
|
|
926
|
+
port: int = 0
|
|
927
|
+
"""The port. Example: `3425`"""
|
|
928
|
+
external_ip: str | None = None
|
|
929
|
+
"""The external IP address of the carrier. Example: `203.0.113.10`"""
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
@dataclasses.dataclass(kw_only=True)
|
|
933
|
+
class Blueprint:
|
|
934
|
+
"""A network blueprint."""
|
|
935
|
+
|
|
936
|
+
name: str = ""
|
|
937
|
+
"""The name of the blueprint."""
|
|
938
|
+
template: str = ""
|
|
939
|
+
"""The template that renders a pipeline configuration. Placeholders such as `{{
|
|
940
|
+
.node.ip }}` are filled in with network and node parameters.
|
|
941
|
+
"""
|
|
942
|
+
read_only: bool = False
|
|
943
|
+
"""Whether the blueprint is read-only. The built-in blueprints are read-only and
|
|
944
|
+
cannot be updated or deleted.
|
|
945
|
+
"""
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
@dataclasses.dataclass(kw_only=True)
|
|
949
|
+
class BlueprintWrite:
|
|
950
|
+
"""The editable fields of a blueprint."""
|
|
951
|
+
|
|
952
|
+
name: str = ""
|
|
953
|
+
"""The name of the blueprint. Example: `UDP relay`"""
|
|
954
|
+
template: str = ""
|
|
955
|
+
"""The template that renders a pipeline configuration. Placeholders such as `{{
|
|
956
|
+
.node.ip }}` are filled in with network and node parameters.
|
|
957
|
+
"""
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
@dataclasses.dataclass(kw_only=True)
|
|
961
|
+
class Carrier:
|
|
962
|
+
"""A connection a node uses to carry network traffic."""
|
|
963
|
+
|
|
964
|
+
address: Address | None = None
|
|
965
|
+
"""The IP address and port of the carrier."""
|
|
966
|
+
interface: str | None = None
|
|
967
|
+
"""The name of the network interface to use. Example: `eth0`"""
|
|
968
|
+
bandwidth_priority: int | None = None
|
|
969
|
+
"""The bandwidth priority of the carrier."""
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
@dataclasses.dataclass(kw_only=True)
|
|
973
|
+
class CreateBlueprintRequest:
|
|
974
|
+
"""Request to create a blueprint."""
|
|
975
|
+
|
|
976
|
+
blueprint: BlueprintWrite = dataclasses.field(default_factory=lambda: BlueprintWrite())
|
|
977
|
+
"""The blueprint to create. Required."""
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
@dataclasses.dataclass(kw_only=True)
|
|
981
|
+
class CreateBlueprintResponse:
|
|
982
|
+
"""The created blueprint."""
|
|
983
|
+
|
|
984
|
+
id: str = ""
|
|
985
|
+
"""The generated ID of the blueprint."""
|
|
986
|
+
blueprint: Blueprint = dataclasses.field(default_factory=lambda: Blueprint())
|
|
987
|
+
"""The created blueprint."""
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
@dataclasses.dataclass(kw_only=True)
|
|
991
|
+
class CreateNetworkRequest:
|
|
992
|
+
"""Request to create a network."""
|
|
993
|
+
|
|
994
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
995
|
+
"""The network to create. Required."""
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
@dataclasses.dataclass(kw_only=True)
|
|
999
|
+
class CreateNetworkResponse:
|
|
1000
|
+
"""The created network."""
|
|
1001
|
+
|
|
1002
|
+
id: str = ""
|
|
1003
|
+
"""The generated ID of the network."""
|
|
1004
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1005
|
+
"""The created network."""
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1009
|
+
class DeleteBlueprintRequest:
|
|
1010
|
+
"""Request to delete a blueprint."""
|
|
1011
|
+
|
|
1012
|
+
id: str = ""
|
|
1013
|
+
"""The ID of the blueprint to delete."""
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1017
|
+
class DeleteBlueprintResponse:
|
|
1018
|
+
"""Empty response to a blueprint deletion."""
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1022
|
+
class DeleteNetworkRequest:
|
|
1023
|
+
"""Request to delete a network."""
|
|
1024
|
+
|
|
1025
|
+
id: str = ""
|
|
1026
|
+
"""The ID of the network to delete."""
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1030
|
+
class DeleteNetworkResponse:
|
|
1031
|
+
"""Empty response to a network deletion."""
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1035
|
+
class GetBlueprintRequest:
|
|
1036
|
+
"""Request for a single blueprint."""
|
|
1037
|
+
|
|
1038
|
+
id: str = ""
|
|
1039
|
+
"""The ID of the blueprint to fetch."""
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1043
|
+
class GetBlueprintResponse:
|
|
1044
|
+
"""A blueprint and its ID."""
|
|
1045
|
+
|
|
1046
|
+
id: str = ""
|
|
1047
|
+
"""The ID of the blueprint."""
|
|
1048
|
+
blueprint: Blueprint = dataclasses.field(default_factory=lambda: Blueprint())
|
|
1049
|
+
"""The blueprint."""
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1053
|
+
class GetBlueprintsRequest:
|
|
1054
|
+
"""Request for all blueprints."""
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1058
|
+
class GetBlueprintsResponse:
|
|
1059
|
+
"""All blueprints."""
|
|
1060
|
+
|
|
1061
|
+
blueprints: list[GetBlueprintResponse] = dataclasses.field(default_factory=list)
|
|
1062
|
+
"""The blueprints with their IDs."""
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1066
|
+
class GetNetworkInstancesRequest:
|
|
1067
|
+
"""Request for the network instances on a node."""
|
|
1068
|
+
|
|
1069
|
+
node_id: str = ""
|
|
1070
|
+
"""The ID of the node to fetch network instances from."""
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1074
|
+
class GetNetworkInstancesResponse:
|
|
1075
|
+
"""The network instances on a node."""
|
|
1076
|
+
|
|
1077
|
+
network_instances: list[NetworkInstance] = dataclasses.field(default_factory=list)
|
|
1078
|
+
"""The network instances of the node."""
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1082
|
+
class GetNetworkPipelinesRequest:
|
|
1083
|
+
"""Request for the network instance pipelines on a node. Leave a filter unset to not
|
|
1084
|
+
filter on it.
|
|
1085
|
+
"""
|
|
1086
|
+
|
|
1087
|
+
node_id: str = ""
|
|
1088
|
+
"""The ID of the node to fetch network instance pipelines from."""
|
|
1089
|
+
optional_network_id: str | None = None
|
|
1090
|
+
"""Only return pipelines belonging to this network ID."""
|
|
1091
|
+
optional_instance_id: str | None = None
|
|
1092
|
+
"""Only return pipelines belonging to this network instance ID."""
|
|
1093
|
+
optional_blueprint_id: str | None = None
|
|
1094
|
+
"""Only return pipelines generated from this blueprint ID."""
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1098
|
+
class GetNetworkPipelinesResponse:
|
|
1099
|
+
"""The matching network instance pipelines."""
|
|
1100
|
+
|
|
1101
|
+
network_pipelines: list[NetworkPipeline] = dataclasses.field(default_factory=list)
|
|
1102
|
+
"""The network instance pipelines."""
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1106
|
+
class GetNetworkRequest:
|
|
1107
|
+
"""Request for a single network."""
|
|
1108
|
+
|
|
1109
|
+
id: str = ""
|
|
1110
|
+
"""The ID of the network to fetch."""
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1114
|
+
class GetNetworkResponse:
|
|
1115
|
+
"""A network and its ID."""
|
|
1116
|
+
|
|
1117
|
+
id: str = ""
|
|
1118
|
+
"""The ID of the network."""
|
|
1119
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1120
|
+
"""The network."""
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1124
|
+
class GetNetworksRequest:
|
|
1125
|
+
"""Request for all networks."""
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1129
|
+
class GetNetworksResponse:
|
|
1130
|
+
"""All networks."""
|
|
1131
|
+
|
|
1132
|
+
networks: list[GetNetworkResponse] = dataclasses.field(default_factory=list)
|
|
1133
|
+
"""The networks with their IDs."""
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1137
|
+
class Network:
|
|
1138
|
+
"""A virtual network connecting nodes through a central relay node."""
|
|
1139
|
+
|
|
1140
|
+
name: str = ""
|
|
1141
|
+
"""The name of the network. Must not be empty. Example: `Office network`"""
|
|
1142
|
+
subnet_cidr: str = ""
|
|
1143
|
+
"""The IPv4 subnet, in CIDR notation, that node IP addresses are assigned from.
|
|
1144
|
+
Example: `100.65.254.0/24`
|
|
1145
|
+
"""
|
|
1146
|
+
blueprints: NetworkBlueprints = dataclasses.field(default_factory=lambda: NetworkBlueprints())
|
|
1147
|
+
"""The blueprints used to generate the network's pipelines."""
|
|
1148
|
+
parameters: str = ""
|
|
1149
|
+
"""Parameters available to the network's blueprints, as a JSON object. May be empty.
|
|
1150
|
+
Example: `{ "raft_timeout": 9000, "loss_emulation_percentage": 1 }`
|
|
1151
|
+
"""
|
|
1152
|
+
relay_node_id: str = ""
|
|
1153
|
+
"""The node ID of the relay node. Must be the node that has networks enabled."""
|
|
1154
|
+
nodes: list[NetworksNode] = dataclasses.field(default_factory=list)
|
|
1155
|
+
"""The nodes in the network, each with its assigned IP address and carriers."""
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1159
|
+
class NetworkBlueprints:
|
|
1160
|
+
"""The blueprint IDs used for each role in a network. A blueprint left unset falls
|
|
1161
|
+
back to the default blueprint for that role configured on the networks node.
|
|
1162
|
+
"""
|
|
1163
|
+
|
|
1164
|
+
relay_blueprint: str | None = None
|
|
1165
|
+
"""ID of the blueprint deployed to the relay node."""
|
|
1166
|
+
relay_client_blueprint: str | None = None
|
|
1167
|
+
"""ID of the blueprint deployed to the relay node once for every client in the
|
|
1168
|
+
network.
|
|
1169
|
+
"""
|
|
1170
|
+
client_blueprint: str | None = None
|
|
1171
|
+
"""ID of the blueprint deployed to every node in the network."""
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1175
|
+
class NetworkInstance:
|
|
1176
|
+
"""A network's instance on one node."""
|
|
1177
|
+
|
|
1178
|
+
id: str = ""
|
|
1179
|
+
"""The ID of the network instance."""
|
|
1180
|
+
network_id: str = ""
|
|
1181
|
+
"""The ID of the network the instance belongs to."""
|
|
1182
|
+
network_name: str = ""
|
|
1183
|
+
"""The name of the network the instance belongs to."""
|
|
1184
|
+
pipeline_ids: list[str] = dataclasses.field(default_factory=list)
|
|
1185
|
+
"""The IDs of the pipelines managed by the network instance."""
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1189
|
+
class NetworkInstanceLogStreamMessages:
|
|
1190
|
+
"""A batch of network instance log messages."""
|
|
1191
|
+
|
|
1192
|
+
messages: list[Message] = dataclasses.field(default_factory=list)
|
|
1193
|
+
"""The log messages."""
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1197
|
+
class NetworkLogStreamMessages:
|
|
1198
|
+
"""A batch of network log messages."""
|
|
1199
|
+
|
|
1200
|
+
messages: list[Message] = dataclasses.field(default_factory=list)
|
|
1201
|
+
"""The log messages."""
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1205
|
+
class NetworkPipeline:
|
|
1206
|
+
"""A pipeline generated for a network instance from one of the network's blueprints.
|
|
1207
|
+
"""
|
|
1208
|
+
|
|
1209
|
+
id: str = ""
|
|
1210
|
+
"""The ID of this network instance pipeline record. Not the same as `pipeline_id`.
|
|
1211
|
+
"""
|
|
1212
|
+
network_id: str = ""
|
|
1213
|
+
"""The ID of the network the pipeline belongs to."""
|
|
1214
|
+
instance_id: str = ""
|
|
1215
|
+
"""The ID of the network instance the pipeline belongs to."""
|
|
1216
|
+
blueprint_id: str = ""
|
|
1217
|
+
"""The ID of the blueprint the pipeline was generated from."""
|
|
1218
|
+
pipeline_id: str = ""
|
|
1219
|
+
"""The ID of the pipeline on the node."""
|
|
1220
|
+
pipeline_name: str = ""
|
|
1221
|
+
"""The name of the pipeline."""
|
|
1222
|
+
enabled: bool = False
|
|
1223
|
+
"""Whether the pipeline is enabled, meaning it should be running."""
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1227
|
+
class NetworksNode:
|
|
1228
|
+
"""A node's membership in a network."""
|
|
1229
|
+
|
|
1230
|
+
node_id: str = ""
|
|
1231
|
+
"""The ID of the node."""
|
|
1232
|
+
node_ip: str = ""
|
|
1233
|
+
"""The node's IP address in the network. Must be unique within the network and
|
|
1234
|
+
cannot be changed. Example: `100.65.254.2`
|
|
1235
|
+
"""
|
|
1236
|
+
carriers: list[Carrier] = dataclasses.field(default_factory=list)
|
|
1237
|
+
"""The carriers the node uses in the network. Each carrier of the relay node needs
|
|
1238
|
+
an `address`; each carrier of a client needs an `address` or an `interface`.
|
|
1239
|
+
"""
|
|
1240
|
+
type: NodeType = NodeType.NODE_TYPE_CLIENT
|
|
1241
|
+
"""The node's role, derived from the network's `relay_node_id`. Cannot be changed
|
|
1242
|
+
directly.
|
|
1243
|
+
"""
|
|
1244
|
+
parameters: str = ""
|
|
1245
|
+
"""Parameters for this node available to the blueprints, as a JSON object. May be
|
|
1246
|
+
empty.
|
|
1247
|
+
"""
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1251
|
+
class NetworksOpenNetworkInstanceLogStreamRequest:
|
|
1252
|
+
"""Request to stream the log of a network instance."""
|
|
1253
|
+
|
|
1254
|
+
node_id: str = ""
|
|
1255
|
+
"""The ID of the node the network instance runs on."""
|
|
1256
|
+
network_instance_id: str = ""
|
|
1257
|
+
"""The ID of the network instance whose log to stream."""
|
|
1258
|
+
options: Options = dataclasses.field(default_factory=lambda: Options())
|
|
1259
|
+
"""Log stream options, such as how many past lines to send first."""
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1263
|
+
class NetworksOpenNetworkLogStreamRequest:
|
|
1264
|
+
"""Request to stream the log of a network."""
|
|
1265
|
+
|
|
1266
|
+
network_id: str = ""
|
|
1267
|
+
"""The ID of the network whose log to stream."""
|
|
1268
|
+
options: Options = dataclasses.field(default_factory=lambda: Options())
|
|
1269
|
+
"""Log stream options, such as how many past lines to send first."""
|
|
1270
|
+
|
|
1271
|
+
|
|
1272
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1273
|
+
class StreamNetworkInstanceCreateEvent:
|
|
1274
|
+
"""Sent when a network instance is created."""
|
|
1275
|
+
|
|
1276
|
+
network_instance: NetworkInstance = dataclasses.field(default_factory=lambda: NetworkInstance())
|
|
1277
|
+
"""The created network instance."""
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1281
|
+
class StreamNetworkInstanceDeleteEvent:
|
|
1282
|
+
"""Sent when a network instance is deleted."""
|
|
1283
|
+
|
|
1284
|
+
network_instance: NetworkInstance = dataclasses.field(default_factory=lambda: NetworkInstance())
|
|
1285
|
+
"""The deleted network instance."""
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1289
|
+
class StreamNetworkInstanceEvent:
|
|
1290
|
+
"""A change to a network instance."""
|
|
1291
|
+
|
|
1292
|
+
create: StreamNetworkInstanceCreateEvent | None = None
|
|
1293
|
+
"""A network instance was created."""
|
|
1294
|
+
update: StreamNetworkInstanceUpdateEvent | None = None
|
|
1295
|
+
"""A network instance was updated."""
|
|
1296
|
+
delete: StreamNetworkInstanceDeleteEvent | None = None
|
|
1297
|
+
"""A network instance was deleted."""
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1301
|
+
class StreamNetworkInstanceUpdateEvent:
|
|
1302
|
+
"""Sent when a network instance or one of its pipelines is updated."""
|
|
1303
|
+
|
|
1304
|
+
network_instance: NetworkInstance = dataclasses.field(default_factory=lambda: NetworkInstance())
|
|
1305
|
+
"""The network instance after the update."""
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1309
|
+
class StreamNetworkInstancesRequest:
|
|
1310
|
+
"""Request to stream network instance changes on a node."""
|
|
1311
|
+
|
|
1312
|
+
node_id: str = ""
|
|
1313
|
+
"""The ID of the node to stream network instances from."""
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1317
|
+
class StreamNetworkPipelineCreateEvent:
|
|
1318
|
+
"""Sent when a network instance pipeline is created."""
|
|
1319
|
+
|
|
1320
|
+
network_pipeline: NetworkPipeline = dataclasses.field(default_factory=lambda: NetworkPipeline())
|
|
1321
|
+
"""The created pipeline."""
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1325
|
+
class StreamNetworkPipelineDeleteEvent:
|
|
1326
|
+
"""Sent when a network instance pipeline is deleted."""
|
|
1327
|
+
|
|
1328
|
+
network_pipeline: NetworkPipeline = dataclasses.field(default_factory=lambda: NetworkPipeline())
|
|
1329
|
+
"""The deleted pipeline."""
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1333
|
+
class StreamNetworkPipelineEvent:
|
|
1334
|
+
"""A change to a network instance pipeline."""
|
|
1335
|
+
|
|
1336
|
+
create: StreamNetworkPipelineCreateEvent | None = None
|
|
1337
|
+
"""A pipeline was created."""
|
|
1338
|
+
update: StreamNetworkPipelineUpdateEvent | None = None
|
|
1339
|
+
"""A pipeline was updated."""
|
|
1340
|
+
delete: StreamNetworkPipelineDeleteEvent | None = None
|
|
1341
|
+
"""A pipeline was deleted."""
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1345
|
+
class StreamNetworkPipelineUpdateEvent:
|
|
1346
|
+
"""Sent when a network instance pipeline is updated."""
|
|
1347
|
+
|
|
1348
|
+
network_pipeline: NetworkPipeline = dataclasses.field(default_factory=lambda: NetworkPipeline())
|
|
1349
|
+
"""The pipeline after the update."""
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1353
|
+
class StreamNetworkPipelinesRequest:
|
|
1354
|
+
"""Request to stream network instance pipeline changes on a node."""
|
|
1355
|
+
|
|
1356
|
+
node_id: str = ""
|
|
1357
|
+
"""The ID of the node to stream network instance pipelines from."""
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1361
|
+
class StreamNetworksCreateEvent:
|
|
1362
|
+
"""Sent when a network is created."""
|
|
1363
|
+
|
|
1364
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1365
|
+
"""The created network."""
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1369
|
+
class StreamNetworksDeleteEvent:
|
|
1370
|
+
"""Sent when a network is deleted."""
|
|
1371
|
+
|
|
1372
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1373
|
+
"""The deleted network."""
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1377
|
+
class StreamNetworksEvent:
|
|
1378
|
+
"""A change to a network."""
|
|
1379
|
+
|
|
1380
|
+
create: StreamNetworksCreateEvent | None = None
|
|
1381
|
+
"""A network was created."""
|
|
1382
|
+
update: StreamNetworksUpdateEvent | None = None
|
|
1383
|
+
"""A network was updated."""
|
|
1384
|
+
delete: StreamNetworksDeleteEvent | None = None
|
|
1385
|
+
"""A network was deleted."""
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1389
|
+
class StreamNetworksRequest:
|
|
1390
|
+
"""Request to stream network changes."""
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1394
|
+
class StreamNetworksUpdateEvent:
|
|
1395
|
+
"""Sent when a network is updated."""
|
|
1396
|
+
|
|
1397
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1398
|
+
"""The network after the update."""
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1402
|
+
class ToggleNetworkPipelineRequest:
|
|
1403
|
+
"""Request to toggle a network instance pipeline. Set exactly one of
|
|
1404
|
+
`optional_pipeline_id` and `optional_instance_pipeline_id`.
|
|
1405
|
+
"""
|
|
1406
|
+
|
|
1407
|
+
node_id: str = ""
|
|
1408
|
+
"""The ID of the node the pipeline runs on."""
|
|
1409
|
+
optional_pipeline_id: str | None = None
|
|
1410
|
+
"""The pipeline's `pipeline_id`."""
|
|
1411
|
+
optional_instance_pipeline_id: str | None = None
|
|
1412
|
+
"""The pipeline's `id`."""
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1416
|
+
class ToggleNetworkPipelineResponse:
|
|
1417
|
+
"""Empty response to a pipeline toggle."""
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1421
|
+
class UpdateBlueprintRequest:
|
|
1422
|
+
"""Request to update a blueprint."""
|
|
1423
|
+
|
|
1424
|
+
id: str = ""
|
|
1425
|
+
"""The ID of the blueprint to update."""
|
|
1426
|
+
blueprint: BlueprintWrite = dataclasses.field(default_factory=lambda: BlueprintWrite())
|
|
1427
|
+
"""The new name and template. Required."""
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1431
|
+
class UpdateBlueprintResponse:
|
|
1432
|
+
"""The updated blueprint."""
|
|
1433
|
+
|
|
1434
|
+
id: str = ""
|
|
1435
|
+
"""The ID of the blueprint."""
|
|
1436
|
+
blueprint: Blueprint = dataclasses.field(default_factory=lambda: Blueprint())
|
|
1437
|
+
"""The blueprint after the update."""
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1441
|
+
class UpdateNetworkRequest:
|
|
1442
|
+
"""Request to update a network."""
|
|
1443
|
+
|
|
1444
|
+
id: str = ""
|
|
1445
|
+
"""The ID of the network to update."""
|
|
1446
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1447
|
+
"""The new settings of the network. Required. All fields replace the current values,
|
|
1448
|
+
except `nodes`: leave it empty to keep the nodes unchanged, or list every current
|
|
1449
|
+
node to edit their carriers and parameters.
|
|
1450
|
+
"""
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1454
|
+
class UpdateNetworkResponse:
|
|
1455
|
+
"""The updated network."""
|
|
1456
|
+
|
|
1457
|
+
id: str = ""
|
|
1458
|
+
"""The ID of the network."""
|
|
1459
|
+
network: Network = dataclasses.field(default_factory=lambda: Network())
|
|
1460
|
+
"""The network after the update."""
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1464
|
+
class CreatePipelineRequest:
|
|
1465
|
+
"""Request to create a pipeline."""
|
|
1466
|
+
|
|
1467
|
+
node_id: str = ""
|
|
1468
|
+
"""ID of the node to create the pipeline on."""
|
|
1469
|
+
name: str = ""
|
|
1470
|
+
"""Name of the pipeline. Example: `UDP tunnel`"""
|
|
1471
|
+
json_config: str = ""
|
|
1472
|
+
"""The pipeline configuration as a JSON string."""
|
|
1473
|
+
restart_policy: RestartPolicy = dataclasses.field(default_factory=lambda: RestartPolicy())
|
|
1474
|
+
"""The restart policy of the pipeline. Leave unset to never restart."""
|
|
1475
|
+
startup_policy: StartupPolicy = dataclasses.field(default_factory=lambda: StartupPolicy())
|
|
1476
|
+
"""The startup policy of the pipeline. Leave unset to start it manually only."""
|
|
1477
|
+
default_logging_level: Level | None = None
|
|
1478
|
+
"""The default logging level."""
|
|
1479
|
+
node_reference_id: str | None = None
|
|
1480
|
+
"""ID of the related node."""
|
|
1481
|
+
instructions_timeout: int | None = None
|
|
1482
|
+
"""The timeout in seconds. Must be greater than 0. Example: `30`"""
|
|
1483
|
+
cpu_pin: int | None = None
|
|
1484
|
+
"""Zero indexed CPU thread number. Must be lower than the node's thread count."""
|
|
1485
|
+
performance_mode: bool | None = None
|
|
1486
|
+
"""True to run the pinned thread in performance mode."""
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1490
|
+
class CreatePipelineResponse:
|
|
1491
|
+
"""The created pipeline."""
|
|
1492
|
+
|
|
1493
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1494
|
+
"""The new pipeline, including its generated `id`."""
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1498
|
+
class DeletePipelineRequest:
|
|
1499
|
+
"""Request to delete a pipeline."""
|
|
1500
|
+
|
|
1501
|
+
node_id: str = ""
|
|
1502
|
+
"""ID of the node that hosts the pipeline."""
|
|
1503
|
+
id: str = ""
|
|
1504
|
+
"""ID of the pipeline to delete."""
|
|
1505
|
+
|
|
1506
|
+
|
|
1507
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1508
|
+
class DeletePipelineResponse:
|
|
1509
|
+
"""Empty response, returned when the pipeline is deleted."""
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1513
|
+
class GetPipelineByIdRequest:
|
|
1514
|
+
"""Request to get a pipeline by its ID."""
|
|
1515
|
+
|
|
1516
|
+
node_id: str = ""
|
|
1517
|
+
"""ID of the node that hosts the pipeline."""
|
|
1518
|
+
id: str = ""
|
|
1519
|
+
"""ID of the pipeline."""
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1523
|
+
class GetPipelineByIdResponse:
|
|
1524
|
+
"""The requested pipeline."""
|
|
1525
|
+
|
|
1526
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1527
|
+
"""The pipeline with the given ID."""
|
|
1528
|
+
|
|
1529
|
+
|
|
1530
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1531
|
+
class GetPipelineByNameRequest:
|
|
1532
|
+
"""Request to get a pipeline by its name."""
|
|
1533
|
+
|
|
1534
|
+
node_id: str = ""
|
|
1535
|
+
"""ID of the node that hosts the pipeline."""
|
|
1536
|
+
name: str = ""
|
|
1537
|
+
"""Exact name of the pipeline. Example: `UDP tunnel`"""
|
|
1538
|
+
|
|
1539
|
+
|
|
1540
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1541
|
+
class GetPipelineByNameResponse:
|
|
1542
|
+
"""The requested pipeline."""
|
|
1543
|
+
|
|
1544
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1545
|
+
"""The pipeline with the given name."""
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1549
|
+
class GetPipelineByRunIdRequest:
|
|
1550
|
+
"""Request to get the pipeline that a run belongs to."""
|
|
1551
|
+
|
|
1552
|
+
node_id: str = ""
|
|
1553
|
+
"""ID of the node that hosts the pipeline."""
|
|
1554
|
+
id: str = ""
|
|
1555
|
+
"""ID of the run."""
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1559
|
+
class GetPipelineByRunIdResponse:
|
|
1560
|
+
"""The pipeline that the run belongs to."""
|
|
1561
|
+
|
|
1562
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1563
|
+
"""The pipeline of the given run."""
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1567
|
+
class GetPipelinesRequest:
|
|
1568
|
+
"""Request to list all pipelines."""
|
|
1569
|
+
|
|
1570
|
+
node_id: str = ""
|
|
1571
|
+
"""ID of the node to list the pipelines of."""
|
|
1572
|
+
|
|
1573
|
+
|
|
1574
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1575
|
+
class GetPipelinesResponse:
|
|
1576
|
+
"""All pipelines on the node."""
|
|
1577
|
+
|
|
1578
|
+
pipelines: list[Pipeline] = dataclasses.field(default_factory=list)
|
|
1579
|
+
"""The pipelines, in no particular order."""
|
|
1580
|
+
|
|
1581
|
+
|
|
1582
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1583
|
+
class Kpi:
|
|
1584
|
+
"""The value of one KPI defined in the pipeline configuration."""
|
|
1585
|
+
|
|
1586
|
+
id: str = ""
|
|
1587
|
+
"""ID of the KPI."""
|
|
1588
|
+
field: str = ""
|
|
1589
|
+
"""Path of the KPI field this value was evaluated for, such as `value`."""
|
|
1590
|
+
error: str | None = None
|
|
1591
|
+
"""The KPI could not be evaluated. Holds the error message."""
|
|
1592
|
+
none_value: bool | None = None
|
|
1593
|
+
"""The KPI expression evaluated to no value."""
|
|
1594
|
+
unresolved: str | None = None
|
|
1595
|
+
"""A metric the KPI uses could not be resolved. Holds the reason."""
|
|
1596
|
+
string_value: str | None = None
|
|
1597
|
+
"""A text value."""
|
|
1598
|
+
uint64_value: int | None = None
|
|
1599
|
+
"""An unsigned 64-bit integer value."""
|
|
1600
|
+
int64_value: int | None = None
|
|
1601
|
+
"""A signed 64-bit integer value."""
|
|
1602
|
+
uint32_value: int | None = None
|
|
1603
|
+
"""An unsigned 32-bit integer value."""
|
|
1604
|
+
int32_value: int | None = None
|
|
1605
|
+
"""A signed 32-bit integer value."""
|
|
1606
|
+
float64_value: float | None = None
|
|
1607
|
+
"""A 64-bit floating point value."""
|
|
1608
|
+
float32_value: float | None = None
|
|
1609
|
+
"""A 32-bit floating point value."""
|
|
1610
|
+
bool_value: bool | None = None
|
|
1611
|
+
"""A boolean value."""
|
|
1612
|
+
enum8_value: int | None = None
|
|
1613
|
+
"""An 8-bit enum value, as its number."""
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1617
|
+
class LogStreamMessages:
|
|
1618
|
+
"""A batch of log messages from a pipeline run."""
|
|
1619
|
+
|
|
1620
|
+
messages: list[Message] = dataclasses.field(default_factory=list)
|
|
1621
|
+
"""The log messages."""
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1625
|
+
class PipelineOpenLogStreamRequest:
|
|
1626
|
+
"""Request to stream the logs of a pipeline run."""
|
|
1627
|
+
|
|
1628
|
+
node_id: str = ""
|
|
1629
|
+
"""ID of the node that hosts the run."""
|
|
1630
|
+
run_id: str = ""
|
|
1631
|
+
"""ID of the run to stream logs from."""
|
|
1632
|
+
options: Options = dataclasses.field(default_factory=lambda: Options())
|
|
1633
|
+
"""Stream options, such as how many past lines to send first. Leave unset to receive
|
|
1634
|
+
only new messages.
|
|
1635
|
+
"""
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1639
|
+
class OpenTelemetryStreamRequest:
|
|
1640
|
+
"""Request to stream the telemetry of a pipeline run."""
|
|
1641
|
+
|
|
1642
|
+
node_id: str = ""
|
|
1643
|
+
"""ID of the node that hosts the run."""
|
|
1644
|
+
run_id: str = ""
|
|
1645
|
+
"""ID of the run to stream telemetry from."""
|
|
1646
|
+
|
|
1647
|
+
|
|
1648
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1649
|
+
class Pipeline:
|
|
1650
|
+
"""A pipeline is an executable composition of network components."""
|
|
1651
|
+
|
|
1652
|
+
id: str = ""
|
|
1653
|
+
"""ID of the pipeline."""
|
|
1654
|
+
name: str = ""
|
|
1655
|
+
"""Name of the pipeline."""
|
|
1656
|
+
started: bool = False
|
|
1657
|
+
"""Whether the pipeline is started."""
|
|
1658
|
+
current_run: str | None = None
|
|
1659
|
+
"""ID of the current run."""
|
|
1660
|
+
json_config: str = ""
|
|
1661
|
+
"""The pipeline configuration as a pretty-printed JSON string."""
|
|
1662
|
+
config_compatability: ConfigCompatability = ConfigCompatability.COMPATIBLE
|
|
1663
|
+
"""Whether the node can run the configuration. Read-only."""
|
|
1664
|
+
restart_policy: RestartPolicy = dataclasses.field(default_factory=lambda: RestartPolicy())
|
|
1665
|
+
"""The restart policy of the pipeline."""
|
|
1666
|
+
startup_policy: StartupPolicy = dataclasses.field(default_factory=lambda: StartupPolicy())
|
|
1667
|
+
"""The startup policy of the pipeline."""
|
|
1668
|
+
default_logging_level: Level = Level.STATE
|
|
1669
|
+
"""The default logging level of the pipeline."""
|
|
1670
|
+
node_reference_id: str | None = None
|
|
1671
|
+
"""ID of the related node."""
|
|
1672
|
+
instructions_timeout: int = 0
|
|
1673
|
+
"""Time in seconds before a pipeline instruction is considered timed out."""
|
|
1674
|
+
cpu_pin: int | None = None
|
|
1675
|
+
"""Zero indexed CPU thread number."""
|
|
1676
|
+
performance_mode: bool = False
|
|
1677
|
+
"""Whether the pinned CPU thread runs in performance mode."""
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1681
|
+
class RestartPolicy:
|
|
1682
|
+
"""Decides whether a pipeline is restarted when its run ends. Unset means never."""
|
|
1683
|
+
|
|
1684
|
+
never: RestartPolicyNever | None = None
|
|
1685
|
+
"""Never restart the pipeline."""
|
|
1686
|
+
always: RestartPolicyAlways | None = None
|
|
1687
|
+
"""Restart the pipeline each time its run ends."""
|
|
1688
|
+
on_failure: RestartPolicyOnFailure | None = None
|
|
1689
|
+
"""Restart the pipeline only when its run fails."""
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1693
|
+
class RestartPolicyAlways:
|
|
1694
|
+
"""Restart the pipeline each time its run ends."""
|
|
1695
|
+
|
|
1696
|
+
max_restarts: int = 0
|
|
1697
|
+
"""Maximum number of restarts. 0 means restart without limit."""
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1701
|
+
class RestartPolicyNever:
|
|
1702
|
+
"""Never restart the pipeline when its run ends."""
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1706
|
+
class RestartPolicyOnFailure:
|
|
1707
|
+
"""Restart the pipeline only when its run fails unexpectedly with a non-zero exit
|
|
1708
|
+
code.
|
|
1709
|
+
"""
|
|
1710
|
+
|
|
1711
|
+
max_restarts: int = 0
|
|
1712
|
+
"""Maximum number of restarts. 0 means restart without limit."""
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1716
|
+
class StartPipelineRequest:
|
|
1717
|
+
"""Request to start a pipeline."""
|
|
1718
|
+
|
|
1719
|
+
node_id: str = ""
|
|
1720
|
+
"""ID of the node that hosts the pipeline."""
|
|
1721
|
+
id: str | None = None
|
|
1722
|
+
"""ID of the pipeline."""
|
|
1723
|
+
name: str | None = None
|
|
1724
|
+
"""Exact name of the pipeline. Fails if more than one pipeline has this name.
|
|
1725
|
+
Example: `UDP tunnel`
|
|
1726
|
+
"""
|
|
1727
|
+
|
|
1728
|
+
|
|
1729
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1730
|
+
class StartPipelineResponse:
|
|
1731
|
+
"""The run created by starting the pipeline."""
|
|
1732
|
+
|
|
1733
|
+
run_id: str = ""
|
|
1734
|
+
"""ID of the new run."""
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1738
|
+
class StartupPolicy:
|
|
1739
|
+
"""Decides whether a pipeline starts by itself when the node's application starts.
|
|
1740
|
+
Unset means manual.
|
|
1741
|
+
"""
|
|
1742
|
+
|
|
1743
|
+
manual: StartupPolicyManual | None = None
|
|
1744
|
+
"""Only start the pipeline when asked to."""
|
|
1745
|
+
auto: StartupPolicyAuto | None = None
|
|
1746
|
+
"""Start the pipeline automatically when the application starts."""
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1750
|
+
class StartupPolicyAuto:
|
|
1751
|
+
"""Start the pipeline automatically when the application starts."""
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1755
|
+
class StartupPolicyManual:
|
|
1756
|
+
"""Do not start the pipeline automatically when the application starts."""
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1760
|
+
class StopPipelineRequest:
|
|
1761
|
+
"""Request to stop a pipeline."""
|
|
1762
|
+
|
|
1763
|
+
node_id: str = ""
|
|
1764
|
+
"""ID of the node that hosts the pipeline."""
|
|
1765
|
+
id: str | None = None
|
|
1766
|
+
"""ID of the pipeline."""
|
|
1767
|
+
name: str | None = None
|
|
1768
|
+
"""Exact name of the pipeline. Fails if more than one pipeline has this name.
|
|
1769
|
+
Example: `UDP tunnel`
|
|
1770
|
+
"""
|
|
1771
|
+
run_id: str | None = None
|
|
1772
|
+
"""ID of the pipeline's current run."""
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1776
|
+
class StopPipelineResponse:
|
|
1777
|
+
"""Empty response, returned when the stop is requested."""
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1781
|
+
class StreamPipelinesCreateEvent:
|
|
1782
|
+
"""A pipeline was created."""
|
|
1783
|
+
|
|
1784
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1785
|
+
"""The created pipeline."""
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1789
|
+
class StreamPipelinesDeleteEvent:
|
|
1790
|
+
"""A pipeline was deleted."""
|
|
1791
|
+
|
|
1792
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1793
|
+
"""The deleted pipeline, as it was before deletion."""
|
|
1794
|
+
|
|
1795
|
+
|
|
1796
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1797
|
+
class StreamPipelinesEvent:
|
|
1798
|
+
"""A single change to a pipeline."""
|
|
1799
|
+
|
|
1800
|
+
create: StreamPipelinesCreateEvent | None = None
|
|
1801
|
+
"""Sent when a pipeline is created."""
|
|
1802
|
+
update: StreamPipelinesUpdateEvent | None = None
|
|
1803
|
+
"""Sent when a pipeline is changed, started or stopped."""
|
|
1804
|
+
delete: StreamPipelinesDeleteEvent | None = None
|
|
1805
|
+
"""Sent when a pipeline is deleted."""
|
|
1806
|
+
|
|
1807
|
+
|
|
1808
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1809
|
+
class StreamPipelinesRequest:
|
|
1810
|
+
"""Request to stream pipeline changes."""
|
|
1811
|
+
|
|
1812
|
+
node_id: str = ""
|
|
1813
|
+
"""ID of the node to stream pipeline changes from."""
|
|
1814
|
+
|
|
1815
|
+
|
|
1816
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1817
|
+
class StreamPipelinesUpdateEvent:
|
|
1818
|
+
"""A pipeline was changed, started or stopped."""
|
|
1819
|
+
|
|
1820
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1821
|
+
"""The pipeline after the change."""
|
|
1822
|
+
|
|
1823
|
+
|
|
1824
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1825
|
+
class TelemetrySample:
|
|
1826
|
+
"""One telemetry sample of a pipeline run."""
|
|
1827
|
+
|
|
1828
|
+
metric_collections: list[Collection] = dataclasses.field(default_factory=list)
|
|
1829
|
+
"""The metrics of the run."""
|
|
1830
|
+
kpis: list[Kpi] = dataclasses.field(default_factory=list)
|
|
1831
|
+
"""The KPI values of the run."""
|
|
1832
|
+
timestamp: datetime.datetime | None = None
|
|
1833
|
+
"""When the sample was taken."""
|
|
1834
|
+
|
|
1835
|
+
|
|
1836
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1837
|
+
class UpdatePipelineRequest:
|
|
1838
|
+
"""Request to update a pipeline. All settings are replaced, so send the full set of
|
|
1839
|
+
values you want to keep.
|
|
1840
|
+
"""
|
|
1841
|
+
|
|
1842
|
+
node_id: str = ""
|
|
1843
|
+
"""ID of the node that hosts the pipeline."""
|
|
1844
|
+
id: str = ""
|
|
1845
|
+
"""ID of the pipeline to update."""
|
|
1846
|
+
name: str = ""
|
|
1847
|
+
"""New name of the pipeline. Example: `UDP tunnel`"""
|
|
1848
|
+
json_config: str = ""
|
|
1849
|
+
"""New pipeline configuration as a JSON string."""
|
|
1850
|
+
restart_policy: RestartPolicy = dataclasses.field(default_factory=lambda: RestartPolicy())
|
|
1851
|
+
"""New restart policy of the pipeline. Unset means never restart."""
|
|
1852
|
+
startup_policy: StartupPolicy = dataclasses.field(default_factory=lambda: StartupPolicy())
|
|
1853
|
+
"""New startup policy of the pipeline. Unset means start manually only."""
|
|
1854
|
+
default_logging_level: Level = Level.STATE
|
|
1855
|
+
"""New default logging level of the pipeline. Unset means `STATE`, not the `INFO`
|
|
1856
|
+
default used on create.
|
|
1857
|
+
"""
|
|
1858
|
+
instructions_timeout: int = 0
|
|
1859
|
+
"""New time in seconds before a pipeline instruction is considered timed out. Must
|
|
1860
|
+
be greater than 0. Example: `30`
|
|
1861
|
+
"""
|
|
1862
|
+
cpu_pin: int | None = None
|
|
1863
|
+
"""Zero indexed CPU thread number. Must be lower than the node's thread count."""
|
|
1864
|
+
performance_mode: bool | None = None
|
|
1865
|
+
"""True to run the pinned thread in performance mode."""
|
|
1866
|
+
node_reference_id: str | None = None
|
|
1867
|
+
"""ID of the related node."""
|
|
1868
|
+
force_restart: bool = False
|
|
1869
|
+
"""If true and the pipeline is running, the pipeline is restarted when the new
|
|
1870
|
+
configuration cannot be applied to the current run. The call then returns once
|
|
1871
|
+
the new run is running.
|
|
1872
|
+
"""
|
|
1873
|
+
|
|
1874
|
+
|
|
1875
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1876
|
+
class UpdatePipelineResponse:
|
|
1877
|
+
"""The updated pipeline."""
|
|
1878
|
+
|
|
1879
|
+
pipeline: Pipeline = dataclasses.field(default_factory=lambda: Pipeline())
|
|
1880
|
+
"""The pipeline after the update."""
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1884
|
+
class Flow:
|
|
1885
|
+
"""Traffic between two endpoints on one interface, tracked in both directions. A
|
|
1886
|
+
flow is dropped once it closes or has been idle for a while.
|
|
1887
|
+
"""
|
|
1888
|
+
|
|
1889
|
+
interface: str = ""
|
|
1890
|
+
"""Name of the interface the flow was captured on."""
|
|
1891
|
+
protocol: str = ""
|
|
1892
|
+
"""`TCP`, `UDP`, `ICMP`, or the IP protocol number for any other protocol."""
|
|
1893
|
+
source_ip: str = ""
|
|
1894
|
+
"""IP address of the side that opened the flow, as far as the node can tell."""
|
|
1895
|
+
source_port: int = 0
|
|
1896
|
+
"""Port on the source side. Zero for protocols without ports."""
|
|
1897
|
+
destination_ip: str = ""
|
|
1898
|
+
"""IP address of the side the flow was opened towards."""
|
|
1899
|
+
destination_port: int = 0
|
|
1900
|
+
"""Port on the destination side. Zero for protocols without ports."""
|
|
1901
|
+
sent_bytes: int = 0
|
|
1902
|
+
"""Total bytes sent from source to destination."""
|
|
1903
|
+
sent_packets: int = 0
|
|
1904
|
+
"""Total packets sent from source to destination."""
|
|
1905
|
+
received_bytes: int = 0
|
|
1906
|
+
"""Total bytes sent from destination to source."""
|
|
1907
|
+
received_packets: int = 0
|
|
1908
|
+
"""Total packets sent from destination to source."""
|
|
1909
|
+
bits_per_second: int = 0
|
|
1910
|
+
"""Current throughput over both directions, in bits per second."""
|
|
1911
|
+
first_seen: datetime.datetime | None = None
|
|
1912
|
+
"""When the first packet of the flow was captured."""
|
|
1913
|
+
last_seen: datetime.datetime | None = None
|
|
1914
|
+
"""When the latest packet of the flow was captured."""
|
|
1915
|
+
|
|
1916
|
+
|
|
1917
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1918
|
+
class FlowsSample:
|
|
1919
|
+
"""The network flows of a node at one point in time."""
|
|
1920
|
+
|
|
1921
|
+
timestamp: datetime.datetime | None = None
|
|
1922
|
+
"""When the snapshot was taken."""
|
|
1923
|
+
flows: list[Flow] = dataclasses.field(default_factory=list)
|
|
1924
|
+
"""Every flow the node currently tracks. Empty when none have been captured."""
|
|
1925
|
+
|
|
1926
|
+
|
|
1927
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1928
|
+
class MetricsSample:
|
|
1929
|
+
"""The resource metrics of a node at one point in time."""
|
|
1930
|
+
|
|
1931
|
+
timestamp: datetime.datetime | None = None
|
|
1932
|
+
"""When the sample was taken."""
|
|
1933
|
+
collections: list[Collection] = dataclasses.field(default_factory=list)
|
|
1934
|
+
"""The metrics, grouped into collections such as `/system/memory` and
|
|
1935
|
+
`/system/disk`.
|
|
1936
|
+
"""
|
|
1937
|
+
|
|
1938
|
+
|
|
1939
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1940
|
+
class OpenFlowsStreamRequest:
|
|
1941
|
+
"""Opens a stream of network flow snapshots."""
|
|
1942
|
+
|
|
1943
|
+
node_id: str = ""
|
|
1944
|
+
"""ID of the node to read flows from."""
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
@dataclasses.dataclass(kw_only=True)
|
|
1948
|
+
class OpenMetricsStreamRequest:
|
|
1949
|
+
"""Opens a stream of resource metrics."""
|
|
1950
|
+
|
|
1951
|
+
node_id: str = ""
|
|
1952
|
+
"""ID of the node to read metrics from."""
|
|
1953
|
+
|
|
1954
|
+
|
|
1955
|
+
class BlueprintsClient:
|
|
1956
|
+
"""A blueprint is a template that generates the pipeline configuration a node runs
|
|
1957
|
+
in a network. It uses [Go template syntax](https://pkg.go.dev/text/template), and
|
|
1958
|
+
placeholders such as the node's IP address and carriers are filled in for each
|
|
1959
|
+
node. Every network uses three blueprints: one for the relay node, one the relay
|
|
1960
|
+
runs for every client, and one for every client node. The built-in blueprints are
|
|
1961
|
+
read-only; create your own to change how networks carry traffic. Blueprints are
|
|
1962
|
+
stored on the connected node that has networks enabled, and calls wait until that
|
|
1963
|
+
node is connected.
|
|
1964
|
+
"""
|
|
1965
|
+
|
|
1966
|
+
def __init__(self, transport: Transport) -> None:
|
|
1967
|
+
self._transport = transport
|
|
1968
|
+
|
|
1969
|
+
def get_blueprint(
|
|
1970
|
+
self,
|
|
1971
|
+
*,
|
|
1972
|
+
id: str = "",
|
|
1973
|
+
) -> GetBlueprintResponse:
|
|
1974
|
+
"""Get a single blueprint.
|
|
1975
|
+
|
|
1976
|
+
Args:
|
|
1977
|
+
id: The ID of the blueprint to fetch.
|
|
1978
|
+
"""
|
|
1979
|
+
return self._transport.unary(
|
|
1980
|
+
[Route("GET", "/v1/blueprints/{id}", "")],
|
|
1981
|
+
GetBlueprintRequest(id=id),
|
|
1982
|
+
GetBlueprintResponse,
|
|
1983
|
+
)
|
|
1984
|
+
|
|
1985
|
+
def get_blueprints(self) -> GetBlueprintsResponse:
|
|
1986
|
+
"""Get all blueprints, including the built-in read-only ones."""
|
|
1987
|
+
return self._transport.unary(
|
|
1988
|
+
[Route("GET", "/v1/blueprints", "")],
|
|
1989
|
+
GetBlueprintsRequest(),
|
|
1990
|
+
GetBlueprintsResponse,
|
|
1991
|
+
)
|
|
1992
|
+
|
|
1993
|
+
def create_blueprint(
|
|
1994
|
+
self,
|
|
1995
|
+
*,
|
|
1996
|
+
blueprint: BlueprintWrite | None = None,
|
|
1997
|
+
) -> CreateBlueprintResponse:
|
|
1998
|
+
"""Create a blueprint and return it.
|
|
1999
|
+
|
|
2000
|
+
Args:
|
|
2001
|
+
blueprint: The blueprint to create. Required.
|
|
2002
|
+
"""
|
|
2003
|
+
return self._transport.unary(
|
|
2004
|
+
[Route("POST", "/v1/blueprints", "blueprint")],
|
|
2005
|
+
CreateBlueprintRequest(blueprint=blueprint or BlueprintWrite()),
|
|
2006
|
+
CreateBlueprintResponse,
|
|
2007
|
+
)
|
|
2008
|
+
|
|
2009
|
+
def update_blueprint(
|
|
2010
|
+
self,
|
|
2011
|
+
*,
|
|
2012
|
+
id: str = "",
|
|
2013
|
+
blueprint: BlueprintWrite | None = None,
|
|
2014
|
+
) -> UpdateBlueprintResponse:
|
|
2015
|
+
"""Replace a blueprint and return the updated blueprint. Networks using the
|
|
2016
|
+
blueprint have their pipelines regenerated. Fails with a permission error for
|
|
2017
|
+
read-only blueprints.
|
|
2018
|
+
|
|
2019
|
+
Args:
|
|
2020
|
+
id: The ID of the blueprint to update.
|
|
2021
|
+
blueprint: The new name and template. Required.
|
|
2022
|
+
"""
|
|
2023
|
+
return self._transport.unary(
|
|
2024
|
+
[Route("PUT", "/v1/blueprints/{id}", "blueprint")],
|
|
2025
|
+
UpdateBlueprintRequest(id=id, blueprint=blueprint or BlueprintWrite()),
|
|
2026
|
+
UpdateBlueprintResponse,
|
|
2027
|
+
)
|
|
2028
|
+
|
|
2029
|
+
def delete_blueprint(
|
|
2030
|
+
self,
|
|
2031
|
+
*,
|
|
2032
|
+
id: str = "",
|
|
2033
|
+
) -> DeleteBlueprintResponse:
|
|
2034
|
+
"""Delete a blueprint. Fails with a permission error for read-only blueprints.
|
|
2035
|
+
|
|
2036
|
+
Args:
|
|
2037
|
+
id: The ID of the blueprint to delete.
|
|
2038
|
+
"""
|
|
2039
|
+
return self._transport.unary(
|
|
2040
|
+
[Route("DELETE", "/v1/blueprints/{id}", "")],
|
|
2041
|
+
DeleteBlueprintRequest(id=id),
|
|
2042
|
+
DeleteBlueprintResponse,
|
|
2043
|
+
)
|
|
2044
|
+
|
|
2045
|
+
|
|
2046
|
+
class ConfigServiceClient:
|
|
2047
|
+
"""Settings stored in the configuration of a node. Use this service to read and
|
|
2048
|
+
change them on any node, such as the carriers a node uses by default when it
|
|
2049
|
+
joins a network.
|
|
2050
|
+
"""
|
|
2051
|
+
|
|
2052
|
+
def __init__(self, transport: Transport) -> None:
|
|
2053
|
+
self._transport = transport
|
|
2054
|
+
|
|
2055
|
+
def get_default_network_carriers(
|
|
2056
|
+
self,
|
|
2057
|
+
*,
|
|
2058
|
+
node_id: str = "",
|
|
2059
|
+
) -> GetDefaultNetworkCarriersResponse:
|
|
2060
|
+
"""Get the default network carriers of a node. These are the carriers the node
|
|
2061
|
+
receives every time it joins a new network. Returns an empty list when none
|
|
2062
|
+
are configured.
|
|
2063
|
+
|
|
2064
|
+
Args:
|
|
2065
|
+
node_id: Id of the node to read the default network carriers from.
|
|
2066
|
+
"""
|
|
2067
|
+
return self._transport.unary(
|
|
2068
|
+
[Route("GET", "/v1/nodes/{node_id}/default-network-carriers", "")],
|
|
2069
|
+
GetDefaultNetworkCarriersRequest(node_id=node_id),
|
|
2070
|
+
GetDefaultNetworkCarriersResponse,
|
|
2071
|
+
)
|
|
2072
|
+
|
|
2073
|
+
def set_default_network_carriers(
|
|
2074
|
+
self,
|
|
2075
|
+
*,
|
|
2076
|
+
node_id: str = "",
|
|
2077
|
+
carriers: DefaultNetworkCarriers | None = None,
|
|
2078
|
+
) -> SetDefaultNetworkCarriersResponse:
|
|
2079
|
+
"""Replace the default network carriers of a node. The new carriers apply to
|
|
2080
|
+
networks the node joins afterwards.
|
|
2081
|
+
|
|
2082
|
+
Args:
|
|
2083
|
+
node_id: Id of the node to set the default network carriers on.
|
|
2084
|
+
carriers: The new default network carriers, replacing the current ones.
|
|
2085
|
+
Leave unset to remove all default carriers.
|
|
2086
|
+
"""
|
|
2087
|
+
return self._transport.unary(
|
|
2088
|
+
[Route("PUT", "/v1/nodes/{node_id}/default-network-carriers", "carriers")],
|
|
2089
|
+
SetDefaultNetworkCarriersRequest(node_id=node_id, carriers=carriers),
|
|
2090
|
+
SetDefaultNetworkCarriersResponse,
|
|
2091
|
+
)
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
class HubClientServiceClient:
|
|
2095
|
+
"""The hub client is the part of every node that connects it to a hub server, the
|
|
2096
|
+
control plane that lets connected nodes find and manage each other. Use this
|
|
2097
|
+
service to sign the node hosting the API in to a hub server, disconnect it,
|
|
2098
|
+
follow its connection state, and read or change the details of nodes.
|
|
2099
|
+
"""
|
|
2100
|
+
|
|
2101
|
+
def __init__(self, transport: Transport) -> None:
|
|
2102
|
+
self._transport = transport
|
|
2103
|
+
|
|
2104
|
+
def get_local_node_id(self) -> GetLocalNodeIdResponse:
|
|
2105
|
+
"""Get the ID of the node hosting the API, and whether it is authenticated with
|
|
2106
|
+
a hub server.
|
|
2107
|
+
"""
|
|
2108
|
+
return self._transport.unary(
|
|
2109
|
+
[Route("GET", "/v1/hub-client/local-node-id", "")],
|
|
2110
|
+
GetLocalNodeIdRequest(),
|
|
2111
|
+
GetLocalNodeIdResponse,
|
|
2112
|
+
)
|
|
2113
|
+
|
|
2114
|
+
def get_node(
|
|
2115
|
+
self,
|
|
2116
|
+
*,
|
|
2117
|
+
node_id: str = "",
|
|
2118
|
+
) -> GetNodeResponse:
|
|
2119
|
+
"""Get the details of a node. Fails with Unavailable when the node cannot be
|
|
2120
|
+
reached.
|
|
2121
|
+
|
|
2122
|
+
Args:
|
|
2123
|
+
node_id: Id of the node to get information about, for example the id
|
|
2124
|
+
returned by getLocalNodeId.
|
|
2125
|
+
"""
|
|
2126
|
+
return self._transport.unary(
|
|
2127
|
+
[Route("GET", "/v1/nodes/{node_id}", "")],
|
|
2128
|
+
GetNodeRequest(node_id=node_id),
|
|
2129
|
+
GetNodeResponse,
|
|
2130
|
+
)
|
|
2131
|
+
|
|
2132
|
+
def set_node(
|
|
2133
|
+
self,
|
|
2134
|
+
*,
|
|
2135
|
+
node_id: str = "",
|
|
2136
|
+
name: str = "",
|
|
2137
|
+
metadata: NodeMetadata | None = None,
|
|
2138
|
+
) -> SetNodeResponse:
|
|
2139
|
+
"""Change the details of a node, replacing the current values. Fails with
|
|
2140
|
+
PermissionDenied when the node's configuration comes from a config file.
|
|
2141
|
+
|
|
2142
|
+
Args:
|
|
2143
|
+
node_id: Id of the node to change.
|
|
2144
|
+
name: New name of the node. Example: `edge-node-1`
|
|
2145
|
+
metadata: New metadata of the node. Replaces all existing metadata, so
|
|
2146
|
+
leaving it empty removes the metadata.
|
|
2147
|
+
"""
|
|
2148
|
+
return self._transport.unary(
|
|
2149
|
+
[Route("PUT", "/v1/nodes/{node_id}", "*")],
|
|
2150
|
+
SetNodeRequest(
|
|
2151
|
+
node_id=node_id,
|
|
2152
|
+
name=name,
|
|
2153
|
+
metadata=metadata or NodeMetadata(),
|
|
2154
|
+
),
|
|
2155
|
+
SetNodeResponse,
|
|
2156
|
+
)
|
|
2157
|
+
|
|
2158
|
+
def authenticate_by_request(
|
|
2159
|
+
self,
|
|
2160
|
+
*,
|
|
2161
|
+
hub_server_address: str = "",
|
|
2162
|
+
) -> AuthenticateByRequestResponse:
|
|
2163
|
+
"""Ask a hub server to authenticate the node hosting the API, and wait for the
|
|
2164
|
+
hub server to accept or reject the request. On success the node stays
|
|
2165
|
+
authenticated, also after a restart. Fails with AlreadyExists if the node is
|
|
2166
|
+
already authenticated, Unauthenticated if the request was rejected,
|
|
2167
|
+
DeadlineExceeded if the hub server did not answer in time, Unavailable if the
|
|
2168
|
+
hub server could not be reached, and NotFound if the hub server does not
|
|
2169
|
+
accept authentication by request.
|
|
2170
|
+
|
|
2171
|
+
Args:
|
|
2172
|
+
hub_server_address: HTTP or HTTPS address of the hub server. Example:
|
|
2173
|
+
`http://127.0.0.1:8769`
|
|
2174
|
+
"""
|
|
2175
|
+
return self._transport.unary(
|
|
2176
|
+
[Route("POST", "/v1/hub-client/authenticate-by-request", "*")],
|
|
2177
|
+
AuthenticateByRequestRequest(hub_server_address=hub_server_address),
|
|
2178
|
+
AuthenticateByRequestResponse,
|
|
2179
|
+
)
|
|
2180
|
+
|
|
2181
|
+
def disconnect(self) -> DisconnectResponse:
|
|
2182
|
+
"""Disconnect the node hosting the API from its hub server. The node always
|
|
2183
|
+
leaves, even if the hub server could not remove it from its list of nodes.
|
|
2184
|
+
"""
|
|
2185
|
+
return self._transport.unary(
|
|
2186
|
+
[Route("POST", "/v1/hub-client/disconnect", "*")],
|
|
2187
|
+
DisconnectRequest(),
|
|
2188
|
+
DisconnectResponse,
|
|
2189
|
+
)
|
|
2190
|
+
|
|
2191
|
+
def stream_connection_state(self) -> ServerStream[StreamConnectionStateResponse]:
|
|
2192
|
+
"""Stream the connection state between the node hosting the API and its hub
|
|
2193
|
+
server. The current state is sent first, then a new message every time the
|
|
2194
|
+
state changes. The stream stays open until the caller closes it.
|
|
2195
|
+
"""
|
|
2196
|
+
return self._transport.server_stream(
|
|
2197
|
+
[Route("GET", "/v1/streams/hub-client/connection-state", "")],
|
|
2198
|
+
StreamConnectionStateRequest(),
|
|
2199
|
+
StreamConnectionStateResponse,
|
|
2200
|
+
)
|
|
2201
|
+
|
|
2202
|
+
|
|
2203
|
+
class HubServerServiceClient:
|
|
2204
|
+
"""A hub server is the control plane of a NanoPing setup: nodes authenticate with
|
|
2205
|
+
it, and every node on the same hub can find and manage the others. Use this
|
|
2206
|
+
service to list the nodes on the hub, follow them as they come and go, remove
|
|
2207
|
+
nodes, and approve or reject nodes that ask to join. The node hosting the API
|
|
2208
|
+
must host the hub server or be authenticated with one, otherwise calls fail with
|
|
2209
|
+
FailedPrecondition.
|
|
2210
|
+
"""
|
|
2211
|
+
|
|
2212
|
+
def __init__(self, transport: Transport) -> None:
|
|
2213
|
+
self._transport = transport
|
|
2214
|
+
|
|
2215
|
+
def get_nodes(
|
|
2216
|
+
self,
|
|
2217
|
+
*,
|
|
2218
|
+
metadata_filters: Mapping[str, NodeMetadataItem] | None = None,
|
|
2219
|
+
service_filters: Sequence[NodeService] = (),
|
|
2220
|
+
) -> GetNodesResponse:
|
|
2221
|
+
"""Get the nodes authenticated with the hub server, optionally filtered.
|
|
2222
|
+
|
|
2223
|
+
Args:
|
|
2224
|
+
metadata_filters: Metadata filters keyed by metadata key. A node is
|
|
2225
|
+
included only if it has every key with an equal value of the same type.
|
|
2226
|
+
Leave empty to not filter by metadata.
|
|
2227
|
+
service_filters: Service filters. A node is included only if it offers
|
|
2228
|
+
every listed service. Leave empty to not filter by service.
|
|
2229
|
+
"""
|
|
2230
|
+
return self._transport.unary(
|
|
2231
|
+
[Route("GET", "/v1/nodes", ""), Route("POST", "/v1/nodes/search", "*")],
|
|
2232
|
+
GetNodesRequest(
|
|
2233
|
+
metadata_filters=dict(metadata_filters or {}),
|
|
2234
|
+
service_filters=list(service_filters),
|
|
2235
|
+
),
|
|
2236
|
+
GetNodesResponse,
|
|
2237
|
+
)
|
|
2238
|
+
|
|
2239
|
+
def remove_node(
|
|
2240
|
+
self,
|
|
2241
|
+
*,
|
|
2242
|
+
node_id: str = "",
|
|
2243
|
+
) -> RemoveNodeResponse:
|
|
2244
|
+
"""Remove a node from the hub server. This disconnects the node from the hub
|
|
2245
|
+
server and removes it from its networks.
|
|
2246
|
+
|
|
2247
|
+
Args:
|
|
2248
|
+
node_id: Id of the node to remove.
|
|
2249
|
+
"""
|
|
2250
|
+
return self._transport.unary(
|
|
2251
|
+
[Route("DELETE", "/v1/nodes/{node_id}", "")],
|
|
2252
|
+
RemoveNodeRequest(node_id=node_id),
|
|
2253
|
+
RemoveNodeResponse,
|
|
2254
|
+
)
|
|
2255
|
+
|
|
2256
|
+
def stream_nodes(
|
|
2257
|
+
self,
|
|
2258
|
+
*,
|
|
2259
|
+
metadata_filters: Mapping[str, NodeMetadataItem] | None = None,
|
|
2260
|
+
service_filters: Sequence[NodeService] = (),
|
|
2261
|
+
) -> ServerStream[StreamNodesResponse]:
|
|
2262
|
+
"""Stream the nodes authenticated with the hub server. The matching nodes are
|
|
2263
|
+
sent first, followed by an update every time a node is authenticated,
|
|
2264
|
+
deauthenticated, connects, disconnects or changes its details. Updates are
|
|
2265
|
+
not filtered. The stream stays open until the caller closes it.
|
|
2266
|
+
|
|
2267
|
+
Args:
|
|
2268
|
+
metadata_filters: Metadata filters keyed by metadata key. A node is
|
|
2269
|
+
included only if it has every key with an equal value of the same type.
|
|
2270
|
+
Leave empty to not filter by metadata.
|
|
2271
|
+
service_filters: Service filters. A node is included only if it offers
|
|
2272
|
+
every listed service. Leave empty to not filter by service.
|
|
2273
|
+
"""
|
|
2274
|
+
return self._transport.server_stream(
|
|
2275
|
+
[
|
|
2276
|
+
Route("GET", "/v1/streams/nodes", ""),
|
|
2277
|
+
Route("POST", "/v1/streams/nodes", "*"),
|
|
2278
|
+
],
|
|
2279
|
+
GetNodesRequest(
|
|
2280
|
+
metadata_filters=dict(metadata_filters or {}),
|
|
2281
|
+
service_filters=list(service_filters),
|
|
2282
|
+
),
|
|
2283
|
+
StreamNodesResponse,
|
|
2284
|
+
)
|
|
2285
|
+
|
|
2286
|
+
def authentication_by_requests(
|
|
2287
|
+
self,
|
|
2288
|
+
) -> BidiStream[AuthenticationByRequestAnswer, AuthenticationByRequestRequest]:
|
|
2289
|
+
"""Receive the authentication requests sent to the hub server on the node
|
|
2290
|
+
hosting the API, and accept or reject each one. Nothing is sent when the
|
|
2291
|
+
stream opens. A request is sent each time a node asks to authenticate, and
|
|
2292
|
+
the caller answers it by sending an answer for that request.
|
|
2293
|
+
"""
|
|
2294
|
+
return self._transport.bidi_stream(
|
|
2295
|
+
Route("POST", "/v1/streams/hub-server/authentication-requests", "*"),
|
|
2296
|
+
AuthenticationByRequestRequest,
|
|
2297
|
+
)
|
|
2298
|
+
|
|
2299
|
+
|
|
2300
|
+
class LoggingServiceClient:
|
|
2301
|
+
"""Every node keeps logs: its application log, and a log for each pipeline run,
|
|
2302
|
+
network and network instance. Use this service to follow a log live or to
|
|
2303
|
+
download a complete log file, from any node.
|
|
2304
|
+
"""
|
|
2305
|
+
|
|
2306
|
+
def __init__(self, transport: Transport) -> None:
|
|
2307
|
+
self._transport = transport
|
|
2308
|
+
|
|
2309
|
+
def open_log_stream(
|
|
2310
|
+
self,
|
|
2311
|
+
*,
|
|
2312
|
+
node_id: str = "",
|
|
2313
|
+
options: Options | None = None,
|
|
2314
|
+
app_log_stream_request: OpenAppLogStreamRequest | None = None,
|
|
2315
|
+
pipeline_run_log_stream_request: OpenPipelineRunLogStreamRequest | None = None,
|
|
2316
|
+
network_log_stream_request: LoggingOpenNetworkLogStreamRequest | None = None,
|
|
2317
|
+
network_instance_log_stream_request: LoggingOpenNetworkInstanceLogStreamRequest | None = None,
|
|
2318
|
+
) -> ServerStream[Messages]:
|
|
2319
|
+
"""Stream the log messages of one log on a node. The requested number of past
|
|
2320
|
+
entries is sent first, then new entries as they are written. Fails with an
|
|
2321
|
+
invalid argument error when the node is invalid or no log is chosen, and ends
|
|
2322
|
+
with an error when the log cannot be read or the node loses its connection.
|
|
2323
|
+
|
|
2324
|
+
Args:
|
|
2325
|
+
node_id: ID of the node whose log to stream.
|
|
2326
|
+
options: Stream options. When unset, only new entries are sent.
|
|
2327
|
+
app_log_stream_request: Stream the node's application log.
|
|
2328
|
+
pipeline_run_log_stream_request: Stream the log of a pipeline run.
|
|
2329
|
+
network_log_stream_request: Stream the log of a network.
|
|
2330
|
+
network_instance_log_stream_request: Stream the log of a network
|
|
2331
|
+
instance.
|
|
2332
|
+
"""
|
|
2333
|
+
return self._transport.server_stream(
|
|
2334
|
+
[Route("POST", "/v1/streams/nodes/{node_id}/logs", "*")],
|
|
2335
|
+
LoggingOpenLogStreamRequest(
|
|
2336
|
+
node_id=node_id,
|
|
2337
|
+
options=options or Options(),
|
|
2338
|
+
app_log_stream_request=app_log_stream_request,
|
|
2339
|
+
pipeline_run_log_stream_request=pipeline_run_log_stream_request,
|
|
2340
|
+
network_log_stream_request=network_log_stream_request,
|
|
2341
|
+
network_instance_log_stream_request=network_instance_log_stream_request,
|
|
2342
|
+
),
|
|
2343
|
+
Messages,
|
|
2344
|
+
)
|
|
2345
|
+
|
|
2346
|
+
def download_log_file(
|
|
2347
|
+
self,
|
|
2348
|
+
*,
|
|
2349
|
+
node_id: str = "",
|
|
2350
|
+
app_log_file_request: DownloadAppLogFileRequest | None = None,
|
|
2351
|
+
pipeline_run_log_file_request: DownloadPipelineRunLogFileRequest | None = None,
|
|
2352
|
+
network_log_file_request: DownloadNetworkLogFileRequest | None = None,
|
|
2353
|
+
network_instance_log_file_request: DownloadNetworkInstanceLogFileRequest | None = None,
|
|
2354
|
+
) -> str:
|
|
2355
|
+
"""Download one complete log file from a node as a series of chunks. Join the
|
|
2356
|
+
chunks in order to get the file. The stream ends when the whole file has been
|
|
2357
|
+
sent, or after an error chunk when the file could not be read.
|
|
2358
|
+
|
|
2359
|
+
Returns the whole file as text.
|
|
2360
|
+
|
|
2361
|
+
Args:
|
|
2362
|
+
node_id: ID of the node that holds the log file.
|
|
2363
|
+
app_log_file_request: Download the node's application log.
|
|
2364
|
+
pipeline_run_log_file_request: Download the log of a pipeline run.
|
|
2365
|
+
network_log_file_request: Download the log of a network.
|
|
2366
|
+
network_instance_log_file_request: Download the log of a network
|
|
2367
|
+
instance.
|
|
2368
|
+
"""
|
|
2369
|
+
return self._transport.text(
|
|
2370
|
+
[Route("GET", "/v1/nodes/{node_id}/log-file", "")],
|
|
2371
|
+
DownloadLogFileRequest(
|
|
2372
|
+
node_id=node_id,
|
|
2373
|
+
app_log_file_request=app_log_file_request,
|
|
2374
|
+
pipeline_run_log_file_request=pipeline_run_log_file_request,
|
|
2375
|
+
network_log_file_request=network_log_file_request,
|
|
2376
|
+
network_instance_log_file_request=network_instance_log_file_request,
|
|
2377
|
+
),
|
|
2378
|
+
)
|
|
2379
|
+
|
|
2380
|
+
|
|
2381
|
+
class NetworkInstancesClient:
|
|
2382
|
+
"""A network instance is a network's presence on one node: the pipelines generated
|
|
2383
|
+
for that node from the network's blueprints. Instances are created, updated and
|
|
2384
|
+
removed automatically when their network changes, so they cannot be managed
|
|
2385
|
+
directly. Use this service to see which networks a node takes part in, follow its
|
|
2386
|
+
network pipelines, turn them on or off, and read their logs. The node needs
|
|
2387
|
+
pipelines enabled.
|
|
2388
|
+
"""
|
|
2389
|
+
|
|
2390
|
+
def __init__(self, transport: Transport) -> None:
|
|
2391
|
+
self._transport = transport
|
|
2392
|
+
|
|
2393
|
+
def get_network_instances(
|
|
2394
|
+
self,
|
|
2395
|
+
*,
|
|
2396
|
+
node_id: str = "",
|
|
2397
|
+
) -> GetNetworkInstancesResponse:
|
|
2398
|
+
"""Get all network instances on a node, each with its pipelines.
|
|
2399
|
+
|
|
2400
|
+
Args:
|
|
2401
|
+
node_id: The ID of the node to fetch network instances from.
|
|
2402
|
+
"""
|
|
2403
|
+
return self._transport.unary(
|
|
2404
|
+
[Route("GET", "/v1/nodes/{node_id}/network-instances", "")],
|
|
2405
|
+
GetNetworkInstancesRequest(node_id=node_id),
|
|
2406
|
+
GetNetworkInstancesResponse,
|
|
2407
|
+
)
|
|
2408
|
+
|
|
2409
|
+
def stream_network_instances(
|
|
2410
|
+
self,
|
|
2411
|
+
*,
|
|
2412
|
+
node_id: str = "",
|
|
2413
|
+
) -> ServerStream[StreamNetworkInstanceEvent]:
|
|
2414
|
+
"""Stream changes to the network instances on a node. Nothing is sent when the
|
|
2415
|
+
stream opens; an event is sent each time an instance is created, updated or
|
|
2416
|
+
deleted, and an update is also sent when one of its pipelines changes. The
|
|
2417
|
+
stream ends if the connection to the node is lost.
|
|
2418
|
+
|
|
2419
|
+
Args:
|
|
2420
|
+
node_id: The ID of the node to stream network instances from.
|
|
2421
|
+
"""
|
|
2422
|
+
return self._transport.server_stream(
|
|
2423
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/network-instances", "")],
|
|
2424
|
+
StreamNetworkInstancesRequest(node_id=node_id),
|
|
2425
|
+
StreamNetworkInstanceEvent,
|
|
2426
|
+
)
|
|
2427
|
+
|
|
2428
|
+
def get_network_pipelines(
|
|
2429
|
+
self,
|
|
2430
|
+
*,
|
|
2431
|
+
node_id: str = "",
|
|
2432
|
+
optional_network_id: str | None = None,
|
|
2433
|
+
optional_instance_id: str | None = None,
|
|
2434
|
+
optional_blueprint_id: str | None = None,
|
|
2435
|
+
) -> GetNetworkPipelinesResponse:
|
|
2436
|
+
"""Get the network instance pipelines on a node, optionally filtered. A pipeline
|
|
2437
|
+
must match every filter that is set.
|
|
2438
|
+
|
|
2439
|
+
Args:
|
|
2440
|
+
node_id: The ID of the node to fetch network instance pipelines from.
|
|
2441
|
+
optional_network_id: Only return pipelines belonging to this network ID.
|
|
2442
|
+
optional_instance_id: Only return pipelines belonging to this network
|
|
2443
|
+
instance ID.
|
|
2444
|
+
optional_blueprint_id: Only return pipelines generated from this
|
|
2445
|
+
blueprint ID.
|
|
2446
|
+
"""
|
|
2447
|
+
return self._transport.unary(
|
|
2448
|
+
[Route("GET", "/v1/nodes/{node_id}/network-pipelines", "")],
|
|
2449
|
+
GetNetworkPipelinesRequest(
|
|
2450
|
+
node_id=node_id,
|
|
2451
|
+
optional_network_id=optional_network_id,
|
|
2452
|
+
optional_instance_id=optional_instance_id,
|
|
2453
|
+
optional_blueprint_id=optional_blueprint_id,
|
|
2454
|
+
),
|
|
2455
|
+
GetNetworkPipelinesResponse,
|
|
2456
|
+
)
|
|
2457
|
+
|
|
2458
|
+
def stream_network_pipelines(
|
|
2459
|
+
self,
|
|
2460
|
+
*,
|
|
2461
|
+
node_id: str = "",
|
|
2462
|
+
) -> ServerStream[StreamNetworkPipelineEvent]:
|
|
2463
|
+
"""Stream changes to the network instance pipelines on a node. Nothing is sent
|
|
2464
|
+
when the stream opens; an event is sent each time a pipeline is created,
|
|
2465
|
+
updated or deleted. The stream ends if the connection to the node is lost.
|
|
2466
|
+
|
|
2467
|
+
Args:
|
|
2468
|
+
node_id: The ID of the node to stream network instance pipelines from.
|
|
2469
|
+
"""
|
|
2470
|
+
return self._transport.server_stream(
|
|
2471
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/network-pipelines", "")],
|
|
2472
|
+
StreamNetworkPipelinesRequest(node_id=node_id),
|
|
2473
|
+
StreamNetworkPipelineEvent,
|
|
2474
|
+
)
|
|
2475
|
+
|
|
2476
|
+
def toggle_network_pipeline(
|
|
2477
|
+
self,
|
|
2478
|
+
*,
|
|
2479
|
+
node_id: str = "",
|
|
2480
|
+
optional_pipeline_id: str | None = None,
|
|
2481
|
+
optional_instance_pipeline_id: str | None = None,
|
|
2482
|
+
) -> ToggleNetworkPipelineResponse:
|
|
2483
|
+
"""Enable or disable a network instance pipeline on a node, which starts or
|
|
2484
|
+
stops the pipeline. Each call flips the current state. Fails with a not found
|
|
2485
|
+
error if no matching pipeline exists.
|
|
2486
|
+
|
|
2487
|
+
Args:
|
|
2488
|
+
node_id: The ID of the node the pipeline runs on.
|
|
2489
|
+
optional_pipeline_id: The pipeline's `pipeline_id`.
|
|
2490
|
+
optional_instance_pipeline_id: The pipeline's `id`.
|
|
2491
|
+
"""
|
|
2492
|
+
return self._transport.unary(
|
|
2493
|
+
[Route("POST", "/v1/nodes/{node_id}/network-pipelines/toggle", "*")],
|
|
2494
|
+
ToggleNetworkPipelineRequest(
|
|
2495
|
+
node_id=node_id,
|
|
2496
|
+
optional_pipeline_id=optional_pipeline_id,
|
|
2497
|
+
optional_instance_pipeline_id=optional_instance_pipeline_id,
|
|
2498
|
+
),
|
|
2499
|
+
ToggleNetworkPipelineResponse,
|
|
2500
|
+
)
|
|
2501
|
+
|
|
2502
|
+
def open_log_stream(
|
|
2503
|
+
self,
|
|
2504
|
+
*,
|
|
2505
|
+
node_id: str = "",
|
|
2506
|
+
network_instance_id: str = "",
|
|
2507
|
+
options: Options | None = None,
|
|
2508
|
+
) -> ServerStream[NetworkInstanceLogStreamMessages]:
|
|
2509
|
+
"""Stream the log messages of a network instance on a node. The requested number
|
|
2510
|
+
of past lines is sent first, then new messages as they are logged, until the
|
|
2511
|
+
connection to the node is lost.
|
|
2512
|
+
|
|
2513
|
+
Args:
|
|
2514
|
+
node_id: The ID of the node the network instance runs on.
|
|
2515
|
+
network_instance_id: The ID of the network instance whose log to stream.
|
|
2516
|
+
options: Log stream options, such as how many past lines to send first.
|
|
2517
|
+
"""
|
|
2518
|
+
return self._transport.server_stream(
|
|
2519
|
+
[
|
|
2520
|
+
Route("GET", "/v1/streams/nodes/{node_id}/network-instances/{network_instance_id}/logs", ""),
|
|
2521
|
+
],
|
|
2522
|
+
NetworksOpenNetworkInstanceLogStreamRequest(
|
|
2523
|
+
node_id=node_id,
|
|
2524
|
+
network_instance_id=network_instance_id,
|
|
2525
|
+
options=options or Options(),
|
|
2526
|
+
),
|
|
2527
|
+
NetworkInstanceLogStreamMessages,
|
|
2528
|
+
)
|
|
2529
|
+
|
|
2530
|
+
|
|
2531
|
+
class NetworksClient:
|
|
2532
|
+
"""A network is a virtual network that connects nodes as if they shared a local
|
|
2533
|
+
network, giving each node its own IP address. All traffic flows through a central
|
|
2534
|
+
relay node. When a network is created or changed, the pipelines each node needs
|
|
2535
|
+
are generated from the network's blueprints and deployed automatically. Use this
|
|
2536
|
+
service to create and change networks and to follow their changes and logs.
|
|
2537
|
+
Networks are stored on the connected node that has networks enabled, and calls
|
|
2538
|
+
wait until that node is connected.
|
|
2539
|
+
"""
|
|
2540
|
+
|
|
2541
|
+
def __init__(self, transport: Transport) -> None:
|
|
2542
|
+
self._transport = transport
|
|
2543
|
+
|
|
2544
|
+
def get_network(
|
|
2545
|
+
self,
|
|
2546
|
+
*,
|
|
2547
|
+
id: str = "",
|
|
2548
|
+
) -> GetNetworkResponse:
|
|
2549
|
+
"""Get a single network.
|
|
2550
|
+
|
|
2551
|
+
Args:
|
|
2552
|
+
id: The ID of the network to fetch.
|
|
2553
|
+
"""
|
|
2554
|
+
return self._transport.unary(
|
|
2555
|
+
[Route("GET", "/v1/networks/{id}", "")],
|
|
2556
|
+
GetNetworkRequest(id=id),
|
|
2557
|
+
GetNetworkResponse,
|
|
2558
|
+
)
|
|
2559
|
+
|
|
2560
|
+
def get_networks(self) -> GetNetworksResponse:
|
|
2561
|
+
"""Get all networks."""
|
|
2562
|
+
return self._transport.unary(
|
|
2563
|
+
[Route("GET", "/v1/networks", "")],
|
|
2564
|
+
GetNetworksRequest(),
|
|
2565
|
+
GetNetworksResponse,
|
|
2566
|
+
)
|
|
2567
|
+
|
|
2568
|
+
def create_network(
|
|
2569
|
+
self,
|
|
2570
|
+
*,
|
|
2571
|
+
network: Network | None = None,
|
|
2572
|
+
) -> CreateNetworkResponse:
|
|
2573
|
+
"""Create a network and return it. Every connected node is added to the network
|
|
2574
|
+
automatically and assigned the first free IP address in its subnet, so nodes
|
|
2575
|
+
given in the request are ignored.
|
|
2576
|
+
|
|
2577
|
+
Args:
|
|
2578
|
+
network: The network to create. Required.
|
|
2579
|
+
"""
|
|
2580
|
+
return self._transport.unary(
|
|
2581
|
+
[Route("POST", "/v1/networks", "network")],
|
|
2582
|
+
CreateNetworkRequest(network=network or Network()),
|
|
2583
|
+
CreateNetworkResponse,
|
|
2584
|
+
)
|
|
2585
|
+
|
|
2586
|
+
def update_network(
|
|
2587
|
+
self,
|
|
2588
|
+
*,
|
|
2589
|
+
id: str = "",
|
|
2590
|
+
network: Network | None = None,
|
|
2591
|
+
) -> UpdateNetworkResponse:
|
|
2592
|
+
"""Replace the settings of an existing network and return the updated network.
|
|
2593
|
+
Nodes cannot be added or removed, and their IP address and role cannot be
|
|
2594
|
+
changed.
|
|
2595
|
+
|
|
2596
|
+
Args:
|
|
2597
|
+
id: The ID of the network to update.
|
|
2598
|
+
network: The new settings of the network. Required. All fields replace
|
|
2599
|
+
the current values, except `nodes`: leave it empty to keep the nodes
|
|
2600
|
+
unchanged, or list every current node to edit their carriers and
|
|
2601
|
+
parameters.
|
|
2602
|
+
"""
|
|
2603
|
+
return self._transport.unary(
|
|
2604
|
+
[Route("PUT", "/v1/networks/{id}", "network")],
|
|
2605
|
+
UpdateNetworkRequest(id=id, network=network or Network()),
|
|
2606
|
+
UpdateNetworkResponse,
|
|
2607
|
+
)
|
|
2608
|
+
|
|
2609
|
+
def delete_network(
|
|
2610
|
+
self,
|
|
2611
|
+
*,
|
|
2612
|
+
id: str = "",
|
|
2613
|
+
) -> DeleteNetworkResponse:
|
|
2614
|
+
"""Delete a network.
|
|
2615
|
+
|
|
2616
|
+
Args:
|
|
2617
|
+
id: The ID of the network to delete.
|
|
2618
|
+
"""
|
|
2619
|
+
return self._transport.unary(
|
|
2620
|
+
[Route("DELETE", "/v1/networks/{id}", "")],
|
|
2621
|
+
DeleteNetworkRequest(id=id),
|
|
2622
|
+
DeleteNetworkResponse,
|
|
2623
|
+
)
|
|
2624
|
+
|
|
2625
|
+
def stream_networks(self) -> ServerStream[StreamNetworksEvent]:
|
|
2626
|
+
"""Stream changes to networks. Nothing is sent when the stream opens; an event
|
|
2627
|
+
is sent each time a network is created, updated or deleted. The stream ends
|
|
2628
|
+
if the connection to the networks node is lost.
|
|
2629
|
+
"""
|
|
2630
|
+
return self._transport.server_stream(
|
|
2631
|
+
[Route("GET", "/v1/streams/networks", "")],
|
|
2632
|
+
StreamNetworksRequest(),
|
|
2633
|
+
StreamNetworksEvent,
|
|
2634
|
+
)
|
|
2635
|
+
|
|
2636
|
+
def open_log_stream(
|
|
2637
|
+
self,
|
|
2638
|
+
*,
|
|
2639
|
+
network_id: str = "",
|
|
2640
|
+
options: Options | None = None,
|
|
2641
|
+
) -> ServerStream[NetworkLogStreamMessages]:
|
|
2642
|
+
"""Stream the log messages of a network. The requested number of past lines is
|
|
2643
|
+
sent first, then new messages as they are logged, until the connection to the
|
|
2644
|
+
networks node is lost.
|
|
2645
|
+
|
|
2646
|
+
Args:
|
|
2647
|
+
network_id: The ID of the network whose log to stream.
|
|
2648
|
+
options: Log stream options, such as how many past lines to send first.
|
|
2649
|
+
"""
|
|
2650
|
+
return self._transport.server_stream(
|
|
2651
|
+
[Route("GET", "/v1/streams/networks/{network_id}/logs", "")],
|
|
2652
|
+
NetworksOpenNetworkLogStreamRequest(
|
|
2653
|
+
network_id=network_id,
|
|
2654
|
+
options=options or Options(),
|
|
2655
|
+
),
|
|
2656
|
+
NetworkLogStreamMessages,
|
|
2657
|
+
)
|
|
2658
|
+
|
|
2659
|
+
|
|
2660
|
+
class PipelinesServiceClient:
|
|
2661
|
+
"""A pipeline is the configuration a node runs to move traffic, connecting
|
|
2662
|
+
components such as UDP sockets, TUN interfaces and error correction encoders into
|
|
2663
|
+
a data flow. Each start of a pipeline creates a new run, with its own logs and
|
|
2664
|
+
telemetry. Use this service to create, change, start and stop pipelines on any
|
|
2665
|
+
node, and to follow their changes, logs and telemetry.
|
|
2666
|
+
"""
|
|
2667
|
+
|
|
2668
|
+
def __init__(self, transport: Transport) -> None:
|
|
2669
|
+
self._transport = transport
|
|
2670
|
+
|
|
2671
|
+
def get_pipelines(
|
|
2672
|
+
self,
|
|
2673
|
+
*,
|
|
2674
|
+
node_id: str = "",
|
|
2675
|
+
) -> GetPipelinesResponse:
|
|
2676
|
+
"""Lists all pipelines on the node.
|
|
2677
|
+
|
|
2678
|
+
Args:
|
|
2679
|
+
node_id: ID of the node to list the pipelines of.
|
|
2680
|
+
"""
|
|
2681
|
+
return self._transport.unary(
|
|
2682
|
+
[Route("GET", "/v1/nodes/{node_id}/pipelines", "")],
|
|
2683
|
+
GetPipelinesRequest(node_id=node_id),
|
|
2684
|
+
GetPipelinesResponse,
|
|
2685
|
+
)
|
|
2686
|
+
|
|
2687
|
+
def get_pipeline_by_id(
|
|
2688
|
+
self,
|
|
2689
|
+
*,
|
|
2690
|
+
node_id: str = "",
|
|
2691
|
+
id: str = "",
|
|
2692
|
+
) -> GetPipelineByIdResponse:
|
|
2693
|
+
"""Get one pipeline. Fails with a not found error if it does not exist.
|
|
2694
|
+
|
|
2695
|
+
Args:
|
|
2696
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2697
|
+
id: ID of the pipeline.
|
|
2698
|
+
"""
|
|
2699
|
+
return self._transport.unary(
|
|
2700
|
+
[Route("GET", "/v1/nodes/{node_id}/pipelines/{id}", "")],
|
|
2701
|
+
GetPipelineByIdRequest(node_id=node_id, id=id),
|
|
2702
|
+
GetPipelineByIdResponse,
|
|
2703
|
+
)
|
|
2704
|
+
|
|
2705
|
+
def get_pipeline_by_name(
|
|
2706
|
+
self,
|
|
2707
|
+
*,
|
|
2708
|
+
node_id: str = "",
|
|
2709
|
+
name: str = "",
|
|
2710
|
+
) -> GetPipelineByNameResponse:
|
|
2711
|
+
"""Get one pipeline by name. Fails with a not found error if no pipeline, or
|
|
2712
|
+
more than one, has that name.
|
|
2713
|
+
|
|
2714
|
+
Args:
|
|
2715
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2716
|
+
name: Exact name of the pipeline. Example: `UDP tunnel`
|
|
2717
|
+
"""
|
|
2718
|
+
return self._transport.unary(
|
|
2719
|
+
[Route("GET", "/v1/nodes/{node_id}/pipelines-by-name/{name}", "")],
|
|
2720
|
+
GetPipelineByNameRequest(node_id=node_id, name=name),
|
|
2721
|
+
GetPipelineByNameResponse,
|
|
2722
|
+
)
|
|
2723
|
+
|
|
2724
|
+
def get_pipeline_by_run_id(
|
|
2725
|
+
self,
|
|
2726
|
+
*,
|
|
2727
|
+
node_id: str = "",
|
|
2728
|
+
id: str = "",
|
|
2729
|
+
) -> GetPipelineByRunIdResponse:
|
|
2730
|
+
"""Get the pipeline that a run belongs to. An unknown run fails with a timeout
|
|
2731
|
+
error.
|
|
2732
|
+
|
|
2733
|
+
Args:
|
|
2734
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2735
|
+
id: ID of the run.
|
|
2736
|
+
"""
|
|
2737
|
+
return self._transport.unary(
|
|
2738
|
+
[Route("GET", "/v1/nodes/{node_id}/pipeline-runs/{id}", "")],
|
|
2739
|
+
GetPipelineByRunIdRequest(node_id=node_id, id=id),
|
|
2740
|
+
GetPipelineByRunIdResponse,
|
|
2741
|
+
)
|
|
2742
|
+
|
|
2743
|
+
def create_pipeline(
|
|
2744
|
+
self,
|
|
2745
|
+
*,
|
|
2746
|
+
node_id: str = "",
|
|
2747
|
+
name: str = "",
|
|
2748
|
+
json_config: str = "",
|
|
2749
|
+
restart_policy: RestartPolicy | None = None,
|
|
2750
|
+
startup_policy: StartupPolicy | None = None,
|
|
2751
|
+
default_logging_level: Level | None = None,
|
|
2752
|
+
node_reference_id: str | None = None,
|
|
2753
|
+
instructions_timeout: int | None = None,
|
|
2754
|
+
cpu_pin: int | None = None,
|
|
2755
|
+
performance_mode: bool | None = None,
|
|
2756
|
+
) -> CreatePipelineResponse:
|
|
2757
|
+
"""Create a pipeline from a JSON configuration and return it. The pipeline is
|
|
2758
|
+
not started. Fails with an invalid argument error if the configuration is
|
|
2759
|
+
invalid or the CPU pin is not a thread of the node.
|
|
2760
|
+
|
|
2761
|
+
Args:
|
|
2762
|
+
node_id: ID of the node to create the pipeline on.
|
|
2763
|
+
name: Name of the pipeline. Example: `UDP tunnel`
|
|
2764
|
+
json_config: The pipeline configuration as a JSON string.
|
|
2765
|
+
restart_policy: The restart policy of the pipeline. Leave unset to never
|
|
2766
|
+
restart.
|
|
2767
|
+
startup_policy: The startup policy of the pipeline. Leave unset to start
|
|
2768
|
+
it manually only.
|
|
2769
|
+
default_logging_level: The default logging level.
|
|
2770
|
+
node_reference_id: ID of the related node.
|
|
2771
|
+
instructions_timeout: The timeout in seconds. Must be greater than 0.
|
|
2772
|
+
Example: `30`
|
|
2773
|
+
cpu_pin: Zero indexed CPU thread number. Must be lower than the node's
|
|
2774
|
+
thread count.
|
|
2775
|
+
performance_mode: True to run the pinned thread in performance mode.
|
|
2776
|
+
"""
|
|
2777
|
+
return self._transport.unary(
|
|
2778
|
+
[Route("POST", "/v1/nodes/{node_id}/pipelines", "*")],
|
|
2779
|
+
CreatePipelineRequest(
|
|
2780
|
+
node_id=node_id,
|
|
2781
|
+
name=name,
|
|
2782
|
+
json_config=json_config,
|
|
2783
|
+
restart_policy=restart_policy or RestartPolicy(),
|
|
2784
|
+
startup_policy=startup_policy or StartupPolicy(),
|
|
2785
|
+
default_logging_level=default_logging_level,
|
|
2786
|
+
node_reference_id=node_reference_id,
|
|
2787
|
+
instructions_timeout=instructions_timeout,
|
|
2788
|
+
cpu_pin=cpu_pin,
|
|
2789
|
+
performance_mode=performance_mode,
|
|
2790
|
+
),
|
|
2791
|
+
CreatePipelineResponse,
|
|
2792
|
+
)
|
|
2793
|
+
|
|
2794
|
+
def update_pipeline(
|
|
2795
|
+
self,
|
|
2796
|
+
*,
|
|
2797
|
+
node_id: str = "",
|
|
2798
|
+
id: str = "",
|
|
2799
|
+
name: str = "",
|
|
2800
|
+
json_config: str = "",
|
|
2801
|
+
restart_policy: RestartPolicy | None = None,
|
|
2802
|
+
startup_policy: StartupPolicy | None = None,
|
|
2803
|
+
default_logging_level: Level = Level.STATE,
|
|
2804
|
+
instructions_timeout: int = 0,
|
|
2805
|
+
cpu_pin: int | None = None,
|
|
2806
|
+
performance_mode: bool | None = None,
|
|
2807
|
+
node_reference_id: str | None = None,
|
|
2808
|
+
force_restart: bool = False,
|
|
2809
|
+
) -> UpdatePipelineResponse:
|
|
2810
|
+
"""Replace the settings of a pipeline and return the updated pipeline. If the
|
|
2811
|
+
pipeline is running and its configuration changed, the new configuration is
|
|
2812
|
+
applied to the current run. If that is not possible, the call fails because
|
|
2813
|
+
the pipeline is running, unless a restart is forced.
|
|
2814
|
+
|
|
2815
|
+
Args:
|
|
2816
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2817
|
+
id: ID of the pipeline to update.
|
|
2818
|
+
name: New name of the pipeline. Example: `UDP tunnel`
|
|
2819
|
+
json_config: New pipeline configuration as a JSON string.
|
|
2820
|
+
restart_policy: New restart policy of the pipeline. Unset means never
|
|
2821
|
+
restart.
|
|
2822
|
+
startup_policy: New startup policy of the pipeline. Unset means start
|
|
2823
|
+
manually only.
|
|
2824
|
+
default_logging_level: New default logging level of the pipeline. Unset
|
|
2825
|
+
means `STATE`, not the `INFO` default used on create.
|
|
2826
|
+
instructions_timeout: New time in seconds before a pipeline instruction
|
|
2827
|
+
is considered timed out. Must be greater than 0. Example: `30`
|
|
2828
|
+
cpu_pin: Zero indexed CPU thread number. Must be lower than the node's
|
|
2829
|
+
thread count.
|
|
2830
|
+
performance_mode: True to run the pinned thread in performance mode.
|
|
2831
|
+
node_reference_id: ID of the related node.
|
|
2832
|
+
force_restart: If true and the pipeline is running, the pipeline is
|
|
2833
|
+
restarted when the new configuration cannot be applied to the current
|
|
2834
|
+
run. The call then returns once the new run is running.
|
|
2835
|
+
"""
|
|
2836
|
+
return self._transport.unary(
|
|
2837
|
+
[Route("PUT", "/v1/nodes/{node_id}/pipelines/{id}", "*")],
|
|
2838
|
+
UpdatePipelineRequest(
|
|
2839
|
+
node_id=node_id,
|
|
2840
|
+
id=id,
|
|
2841
|
+
name=name,
|
|
2842
|
+
json_config=json_config,
|
|
2843
|
+
restart_policy=restart_policy or RestartPolicy(),
|
|
2844
|
+
startup_policy=startup_policy or StartupPolicy(),
|
|
2845
|
+
default_logging_level=default_logging_level,
|
|
2846
|
+
instructions_timeout=instructions_timeout,
|
|
2847
|
+
cpu_pin=cpu_pin,
|
|
2848
|
+
performance_mode=performance_mode,
|
|
2849
|
+
node_reference_id=node_reference_id,
|
|
2850
|
+
force_restart=force_restart,
|
|
2851
|
+
),
|
|
2852
|
+
UpdatePipelineResponse,
|
|
2853
|
+
)
|
|
2854
|
+
|
|
2855
|
+
def delete_pipeline(
|
|
2856
|
+
self,
|
|
2857
|
+
*,
|
|
2858
|
+
node_id: str = "",
|
|
2859
|
+
id: str = "",
|
|
2860
|
+
) -> DeletePipelineResponse:
|
|
2861
|
+
"""Delete a pipeline. Fails with a not found error if it does not exist.
|
|
2862
|
+
|
|
2863
|
+
Args:
|
|
2864
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2865
|
+
id: ID of the pipeline to delete.
|
|
2866
|
+
"""
|
|
2867
|
+
return self._transport.unary(
|
|
2868
|
+
[Route("DELETE", "/v1/nodes/{node_id}/pipelines/{id}", "")],
|
|
2869
|
+
DeletePipelineRequest(node_id=node_id, id=id),
|
|
2870
|
+
DeletePipelineResponse,
|
|
2871
|
+
)
|
|
2872
|
+
|
|
2873
|
+
def start_pipeline(
|
|
2874
|
+
self,
|
|
2875
|
+
*,
|
|
2876
|
+
node_id: str = "",
|
|
2877
|
+
id: str | None = None,
|
|
2878
|
+
name: str | None = None,
|
|
2879
|
+
) -> StartPipelineResponse:
|
|
2880
|
+
"""Start a pipeline and return its new run once it is running. Fails if the
|
|
2881
|
+
pipeline is unknown, already started, or does not reach the running state
|
|
2882
|
+
within 10 seconds.
|
|
2883
|
+
|
|
2884
|
+
Args:
|
|
2885
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2886
|
+
id: ID of the pipeline.
|
|
2887
|
+
name: Exact name of the pipeline. Fails if more than one pipeline has
|
|
2888
|
+
this name. Example: `UDP tunnel`
|
|
2889
|
+
"""
|
|
2890
|
+
return self._transport.unary(
|
|
2891
|
+
[
|
|
2892
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines/{id}/start", ""),
|
|
2893
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines-by-name/{name}/start", ""),
|
|
2894
|
+
],
|
|
2895
|
+
StartPipelineRequest(node_id=node_id, id=id, name=name),
|
|
2896
|
+
StartPipelineResponse,
|
|
2897
|
+
)
|
|
2898
|
+
|
|
2899
|
+
def stop_pipeline(
|
|
2900
|
+
self,
|
|
2901
|
+
*,
|
|
2902
|
+
node_id: str = "",
|
|
2903
|
+
id: str | None = None,
|
|
2904
|
+
name: str | None = None,
|
|
2905
|
+
run_id: str | None = None,
|
|
2906
|
+
) -> StopPipelineResponse:
|
|
2907
|
+
"""Stop a pipeline, found by its ID, its name or its current run. Returns once
|
|
2908
|
+
the stop is requested, without waiting for the run to end. Fails if the
|
|
2909
|
+
pipeline is unknown or already stopped.
|
|
2910
|
+
|
|
2911
|
+
Args:
|
|
2912
|
+
node_id: ID of the node that hosts the pipeline.
|
|
2913
|
+
id: ID of the pipeline.
|
|
2914
|
+
name: Exact name of the pipeline. Fails if more than one pipeline has
|
|
2915
|
+
this name. Example: `UDP tunnel`
|
|
2916
|
+
run_id: ID of the pipeline's current run.
|
|
2917
|
+
"""
|
|
2918
|
+
return self._transport.unary(
|
|
2919
|
+
[
|
|
2920
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines/{id}/stop", ""),
|
|
2921
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines-by-name/{name}/stop", ""),
|
|
2922
|
+
Route("POST", "/v1/nodes/{node_id}/pipeline-runs/{run_id}/stop", ""),
|
|
2923
|
+
],
|
|
2924
|
+
StopPipelineRequest(node_id=node_id, id=id, name=name, run_id=run_id),
|
|
2925
|
+
StopPipelineResponse,
|
|
2926
|
+
)
|
|
2927
|
+
|
|
2928
|
+
def stream_pipelines(
|
|
2929
|
+
self,
|
|
2930
|
+
*,
|
|
2931
|
+
node_id: str = "",
|
|
2932
|
+
) -> ServerStream[StreamPipelinesEvent]:
|
|
2933
|
+
"""Stream changes to the pipelines of a node. Nothing is sent when the stream
|
|
2934
|
+
opens, so get the pipelines first for the current list. An event is sent each
|
|
2935
|
+
time a pipeline is created, updated or deleted, and when a pipeline starts or
|
|
2936
|
+
stops.
|
|
2937
|
+
|
|
2938
|
+
Args:
|
|
2939
|
+
node_id: ID of the node to stream pipeline changes from.
|
|
2940
|
+
"""
|
|
2941
|
+
return self._transport.server_stream(
|
|
2942
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/pipelines", "")],
|
|
2943
|
+
StreamPipelinesRequest(node_id=node_id),
|
|
2944
|
+
StreamPipelinesEvent,
|
|
2945
|
+
)
|
|
2946
|
+
|
|
2947
|
+
def open_log_stream(
|
|
2948
|
+
self,
|
|
2949
|
+
*,
|
|
2950
|
+
node_id: str = "",
|
|
2951
|
+
run_id: str = "",
|
|
2952
|
+
options: Options | None = None,
|
|
2953
|
+
) -> ServerStream[LogStreamMessages]:
|
|
2954
|
+
"""Stream the log messages of a pipeline run. The requested number of past lines
|
|
2955
|
+
is sent first, then new messages as they are logged.
|
|
2956
|
+
|
|
2957
|
+
Args:
|
|
2958
|
+
node_id: ID of the node that hosts the run.
|
|
2959
|
+
run_id: ID of the run to stream logs from.
|
|
2960
|
+
options: Stream options, such as how many past lines to send first.
|
|
2961
|
+
Leave unset to receive only new messages.
|
|
2962
|
+
"""
|
|
2963
|
+
return self._transport.server_stream(
|
|
2964
|
+
[
|
|
2965
|
+
Route("GET", "/v1/streams/nodes/{node_id}/pipeline-runs/{run_id}/logs", ""),
|
|
2966
|
+
],
|
|
2967
|
+
PipelineOpenLogStreamRequest(
|
|
2968
|
+
node_id=node_id,
|
|
2969
|
+
run_id=run_id,
|
|
2970
|
+
options=options or Options(),
|
|
2971
|
+
),
|
|
2972
|
+
LogStreamMessages,
|
|
2973
|
+
)
|
|
2974
|
+
|
|
2975
|
+
def open_telemetry_stream(
|
|
2976
|
+
self,
|
|
2977
|
+
*,
|
|
2978
|
+
node_id: str = "",
|
|
2979
|
+
run_id: str = "",
|
|
2980
|
+
) -> ServerStream[TelemetrySample]:
|
|
2981
|
+
"""Streams telemetry samples (metrics and KPI values) of a pipeline run at
|
|
2982
|
+
regular intervals while the run is active. The stream ends with an error when
|
|
2983
|
+
the run stops, when the run is unknown, or when the node disconnects.
|
|
2984
|
+
|
|
2985
|
+
Args:
|
|
2986
|
+
node_id: ID of the node that hosts the run.
|
|
2987
|
+
run_id: ID of the run to stream telemetry from.
|
|
2988
|
+
"""
|
|
2989
|
+
return self._transport.server_stream(
|
|
2990
|
+
[
|
|
2991
|
+
Route("GET", "/v1/streams/nodes/{node_id}/pipeline-runs/{run_id}/telemetry", ""),
|
|
2992
|
+
],
|
|
2993
|
+
OpenTelemetryStreamRequest(node_id=node_id, run_id=run_id),
|
|
2994
|
+
TelemetrySample,
|
|
2995
|
+
)
|
|
2996
|
+
|
|
2997
|
+
|
|
2998
|
+
class ResourcesServiceClient:
|
|
2999
|
+
"""Live system information of a node: resource metrics such as CPU, memory, storage
|
|
3000
|
+
and network interface usage, and the network flows crossing its interfaces. Use
|
|
3001
|
+
this service to monitor the health and traffic of any node.
|
|
3002
|
+
"""
|
|
3003
|
+
|
|
3004
|
+
def __init__(self, transport: Transport) -> None:
|
|
3005
|
+
self._transport = transport
|
|
3006
|
+
|
|
3007
|
+
def open_metrics_stream(
|
|
3008
|
+
self,
|
|
3009
|
+
*,
|
|
3010
|
+
node_id: str = "",
|
|
3011
|
+
) -> ServerStream[MetricsSample]:
|
|
3012
|
+
"""Stream the resource metrics of a node, such as CPU, memory, disk and network
|
|
3013
|
+
interface usage. A sample of the current metrics is sent when the stream
|
|
3014
|
+
opens. The stream stays open until the client closes it, and ends with an
|
|
3015
|
+
error if the node loses its connection.
|
|
3016
|
+
|
|
3017
|
+
Args:
|
|
3018
|
+
node_id: ID of the node to read metrics from.
|
|
3019
|
+
"""
|
|
3020
|
+
return self._transport.server_stream(
|
|
3021
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/metrics", "")],
|
|
3022
|
+
OpenMetricsStreamRequest(node_id=node_id),
|
|
3023
|
+
MetricsSample,
|
|
3024
|
+
)
|
|
3025
|
+
|
|
3026
|
+
def open_flows_stream(
|
|
3027
|
+
self,
|
|
3028
|
+
*,
|
|
3029
|
+
node_id: str = "",
|
|
3030
|
+
) -> ServerStream[FlowsSample]:
|
|
3031
|
+
"""Stream a snapshot of the network flows crossing the interfaces of a node,
|
|
3032
|
+
about once a second, starting right away. The node only captures packets
|
|
3033
|
+
while someone watches its flows, so the first samples may be empty or
|
|
3034
|
+
incomplete.
|
|
3035
|
+
|
|
3036
|
+
Args:
|
|
3037
|
+
node_id: ID of the node to read flows from.
|
|
3038
|
+
"""
|
|
3039
|
+
return self._transport.server_stream(
|
|
3040
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/flows", "")],
|
|
3041
|
+
OpenFlowsStreamRequest(node_id=node_id),
|
|
3042
|
+
FlowsSample,
|
|
3043
|
+
)
|
|
3044
|
+
|
|
3045
|
+
|
|
3046
|
+
class AsyncBlueprintsClient:
|
|
3047
|
+
"""A blueprint is a template that generates the pipeline configuration a node runs
|
|
3048
|
+
in a network. It uses [Go template syntax](https://pkg.go.dev/text/template), and
|
|
3049
|
+
placeholders such as the node's IP address and carriers are filled in for each
|
|
3050
|
+
node. Every network uses three blueprints: one for the relay node, one the relay
|
|
3051
|
+
runs for every client, and one for every client node. The built-in blueprints are
|
|
3052
|
+
read-only; create your own to change how networks carry traffic. Blueprints are
|
|
3053
|
+
stored on the connected node that has networks enabled, and calls wait until that
|
|
3054
|
+
node is connected.
|
|
3055
|
+
"""
|
|
3056
|
+
|
|
3057
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3058
|
+
self._transport = transport
|
|
3059
|
+
|
|
3060
|
+
async def get_blueprint(
|
|
3061
|
+
self,
|
|
3062
|
+
*,
|
|
3063
|
+
id: str = "",
|
|
3064
|
+
) -> GetBlueprintResponse:
|
|
3065
|
+
"""Get a single blueprint.
|
|
3066
|
+
|
|
3067
|
+
Args:
|
|
3068
|
+
id: The ID of the blueprint to fetch.
|
|
3069
|
+
"""
|
|
3070
|
+
return await self._transport.unary(
|
|
3071
|
+
[Route("GET", "/v1/blueprints/{id}", "")],
|
|
3072
|
+
GetBlueprintRequest(id=id),
|
|
3073
|
+
GetBlueprintResponse,
|
|
3074
|
+
)
|
|
3075
|
+
|
|
3076
|
+
async def get_blueprints(self) -> GetBlueprintsResponse:
|
|
3077
|
+
"""Get all blueprints, including the built-in read-only ones."""
|
|
3078
|
+
return await self._transport.unary(
|
|
3079
|
+
[Route("GET", "/v1/blueprints", "")],
|
|
3080
|
+
GetBlueprintsRequest(),
|
|
3081
|
+
GetBlueprintsResponse,
|
|
3082
|
+
)
|
|
3083
|
+
|
|
3084
|
+
async def create_blueprint(
|
|
3085
|
+
self,
|
|
3086
|
+
*,
|
|
3087
|
+
blueprint: BlueprintWrite | None = None,
|
|
3088
|
+
) -> CreateBlueprintResponse:
|
|
3089
|
+
"""Create a blueprint and return it.
|
|
3090
|
+
|
|
3091
|
+
Args:
|
|
3092
|
+
blueprint: The blueprint to create. Required.
|
|
3093
|
+
"""
|
|
3094
|
+
return await self._transport.unary(
|
|
3095
|
+
[Route("POST", "/v1/blueprints", "blueprint")],
|
|
3096
|
+
CreateBlueprintRequest(blueprint=blueprint or BlueprintWrite()),
|
|
3097
|
+
CreateBlueprintResponse,
|
|
3098
|
+
)
|
|
3099
|
+
|
|
3100
|
+
async def update_blueprint(
|
|
3101
|
+
self,
|
|
3102
|
+
*,
|
|
3103
|
+
id: str = "",
|
|
3104
|
+
blueprint: BlueprintWrite | None = None,
|
|
3105
|
+
) -> UpdateBlueprintResponse:
|
|
3106
|
+
"""Replace a blueprint and return the updated blueprint. Networks using the
|
|
3107
|
+
blueprint have their pipelines regenerated. Fails with a permission error for
|
|
3108
|
+
read-only blueprints.
|
|
3109
|
+
|
|
3110
|
+
Args:
|
|
3111
|
+
id: The ID of the blueprint to update.
|
|
3112
|
+
blueprint: The new name and template. Required.
|
|
3113
|
+
"""
|
|
3114
|
+
return await self._transport.unary(
|
|
3115
|
+
[Route("PUT", "/v1/blueprints/{id}", "blueprint")],
|
|
3116
|
+
UpdateBlueprintRequest(id=id, blueprint=blueprint or BlueprintWrite()),
|
|
3117
|
+
UpdateBlueprintResponse,
|
|
3118
|
+
)
|
|
3119
|
+
|
|
3120
|
+
async def delete_blueprint(
|
|
3121
|
+
self,
|
|
3122
|
+
*,
|
|
3123
|
+
id: str = "",
|
|
3124
|
+
) -> DeleteBlueprintResponse:
|
|
3125
|
+
"""Delete a blueprint. Fails with a permission error for read-only blueprints.
|
|
3126
|
+
|
|
3127
|
+
Args:
|
|
3128
|
+
id: The ID of the blueprint to delete.
|
|
3129
|
+
"""
|
|
3130
|
+
return await self._transport.unary(
|
|
3131
|
+
[Route("DELETE", "/v1/blueprints/{id}", "")],
|
|
3132
|
+
DeleteBlueprintRequest(id=id),
|
|
3133
|
+
DeleteBlueprintResponse,
|
|
3134
|
+
)
|
|
3135
|
+
|
|
3136
|
+
|
|
3137
|
+
class AsyncConfigServiceClient:
|
|
3138
|
+
"""Settings stored in the configuration of a node. Use this service to read and
|
|
3139
|
+
change them on any node, such as the carriers a node uses by default when it
|
|
3140
|
+
joins a network.
|
|
3141
|
+
"""
|
|
3142
|
+
|
|
3143
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3144
|
+
self._transport = transport
|
|
3145
|
+
|
|
3146
|
+
async def get_default_network_carriers(
|
|
3147
|
+
self,
|
|
3148
|
+
*,
|
|
3149
|
+
node_id: str = "",
|
|
3150
|
+
) -> GetDefaultNetworkCarriersResponse:
|
|
3151
|
+
"""Get the default network carriers of a node. These are the carriers the node
|
|
3152
|
+
receives every time it joins a new network. Returns an empty list when none
|
|
3153
|
+
are configured.
|
|
3154
|
+
|
|
3155
|
+
Args:
|
|
3156
|
+
node_id: Id of the node to read the default network carriers from.
|
|
3157
|
+
"""
|
|
3158
|
+
return await self._transport.unary(
|
|
3159
|
+
[Route("GET", "/v1/nodes/{node_id}/default-network-carriers", "")],
|
|
3160
|
+
GetDefaultNetworkCarriersRequest(node_id=node_id),
|
|
3161
|
+
GetDefaultNetworkCarriersResponse,
|
|
3162
|
+
)
|
|
3163
|
+
|
|
3164
|
+
async def set_default_network_carriers(
|
|
3165
|
+
self,
|
|
3166
|
+
*,
|
|
3167
|
+
node_id: str = "",
|
|
3168
|
+
carriers: DefaultNetworkCarriers | None = None,
|
|
3169
|
+
) -> SetDefaultNetworkCarriersResponse:
|
|
3170
|
+
"""Replace the default network carriers of a node. The new carriers apply to
|
|
3171
|
+
networks the node joins afterwards.
|
|
3172
|
+
|
|
3173
|
+
Args:
|
|
3174
|
+
node_id: Id of the node to set the default network carriers on.
|
|
3175
|
+
carriers: The new default network carriers, replacing the current ones.
|
|
3176
|
+
Leave unset to remove all default carriers.
|
|
3177
|
+
"""
|
|
3178
|
+
return await self._transport.unary(
|
|
3179
|
+
[Route("PUT", "/v1/nodes/{node_id}/default-network-carriers", "carriers")],
|
|
3180
|
+
SetDefaultNetworkCarriersRequest(node_id=node_id, carriers=carriers),
|
|
3181
|
+
SetDefaultNetworkCarriersResponse,
|
|
3182
|
+
)
|
|
3183
|
+
|
|
3184
|
+
|
|
3185
|
+
class AsyncHubClientServiceClient:
|
|
3186
|
+
"""The hub client is the part of every node that connects it to a hub server, the
|
|
3187
|
+
control plane that lets connected nodes find and manage each other. Use this
|
|
3188
|
+
service to sign the node hosting the API in to a hub server, disconnect it,
|
|
3189
|
+
follow its connection state, and read or change the details of nodes.
|
|
3190
|
+
"""
|
|
3191
|
+
|
|
3192
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3193
|
+
self._transport = transport
|
|
3194
|
+
|
|
3195
|
+
async def get_local_node_id(self) -> GetLocalNodeIdResponse:
|
|
3196
|
+
"""Get the ID of the node hosting the API, and whether it is authenticated with
|
|
3197
|
+
a hub server.
|
|
3198
|
+
"""
|
|
3199
|
+
return await self._transport.unary(
|
|
3200
|
+
[Route("GET", "/v1/hub-client/local-node-id", "")],
|
|
3201
|
+
GetLocalNodeIdRequest(),
|
|
3202
|
+
GetLocalNodeIdResponse,
|
|
3203
|
+
)
|
|
3204
|
+
|
|
3205
|
+
async def get_node(
|
|
3206
|
+
self,
|
|
3207
|
+
*,
|
|
3208
|
+
node_id: str = "",
|
|
3209
|
+
) -> GetNodeResponse:
|
|
3210
|
+
"""Get the details of a node. Fails with Unavailable when the node cannot be
|
|
3211
|
+
reached.
|
|
3212
|
+
|
|
3213
|
+
Args:
|
|
3214
|
+
node_id: Id of the node to get information about, for example the id
|
|
3215
|
+
returned by getLocalNodeId.
|
|
3216
|
+
"""
|
|
3217
|
+
return await self._transport.unary(
|
|
3218
|
+
[Route("GET", "/v1/nodes/{node_id}", "")],
|
|
3219
|
+
GetNodeRequest(node_id=node_id),
|
|
3220
|
+
GetNodeResponse,
|
|
3221
|
+
)
|
|
3222
|
+
|
|
3223
|
+
async def set_node(
|
|
3224
|
+
self,
|
|
3225
|
+
*,
|
|
3226
|
+
node_id: str = "",
|
|
3227
|
+
name: str = "",
|
|
3228
|
+
metadata: NodeMetadata | None = None,
|
|
3229
|
+
) -> SetNodeResponse:
|
|
3230
|
+
"""Change the details of a node, replacing the current values. Fails with
|
|
3231
|
+
PermissionDenied when the node's configuration comes from a config file.
|
|
3232
|
+
|
|
3233
|
+
Args:
|
|
3234
|
+
node_id: Id of the node to change.
|
|
3235
|
+
name: New name of the node. Example: `edge-node-1`
|
|
3236
|
+
metadata: New metadata of the node. Replaces all existing metadata, so
|
|
3237
|
+
leaving it empty removes the metadata.
|
|
3238
|
+
"""
|
|
3239
|
+
return await self._transport.unary(
|
|
3240
|
+
[Route("PUT", "/v1/nodes/{node_id}", "*")],
|
|
3241
|
+
SetNodeRequest(
|
|
3242
|
+
node_id=node_id,
|
|
3243
|
+
name=name,
|
|
3244
|
+
metadata=metadata or NodeMetadata(),
|
|
3245
|
+
),
|
|
3246
|
+
SetNodeResponse,
|
|
3247
|
+
)
|
|
3248
|
+
|
|
3249
|
+
async def authenticate_by_request(
|
|
3250
|
+
self,
|
|
3251
|
+
*,
|
|
3252
|
+
hub_server_address: str = "",
|
|
3253
|
+
) -> AuthenticateByRequestResponse:
|
|
3254
|
+
"""Ask a hub server to authenticate the node hosting the API, and wait for the
|
|
3255
|
+
hub server to accept or reject the request. On success the node stays
|
|
3256
|
+
authenticated, also after a restart. Fails with AlreadyExists if the node is
|
|
3257
|
+
already authenticated, Unauthenticated if the request was rejected,
|
|
3258
|
+
DeadlineExceeded if the hub server did not answer in time, Unavailable if the
|
|
3259
|
+
hub server could not be reached, and NotFound if the hub server does not
|
|
3260
|
+
accept authentication by request.
|
|
3261
|
+
|
|
3262
|
+
Args:
|
|
3263
|
+
hub_server_address: HTTP or HTTPS address of the hub server. Example:
|
|
3264
|
+
`http://127.0.0.1:8769`
|
|
3265
|
+
"""
|
|
3266
|
+
return await self._transport.unary(
|
|
3267
|
+
[Route("POST", "/v1/hub-client/authenticate-by-request", "*")],
|
|
3268
|
+
AuthenticateByRequestRequest(hub_server_address=hub_server_address),
|
|
3269
|
+
AuthenticateByRequestResponse,
|
|
3270
|
+
)
|
|
3271
|
+
|
|
3272
|
+
async def disconnect(self) -> DisconnectResponse:
|
|
3273
|
+
"""Disconnect the node hosting the API from its hub server. The node always
|
|
3274
|
+
leaves, even if the hub server could not remove it from its list of nodes.
|
|
3275
|
+
"""
|
|
3276
|
+
return await self._transport.unary(
|
|
3277
|
+
[Route("POST", "/v1/hub-client/disconnect", "*")],
|
|
3278
|
+
DisconnectRequest(),
|
|
3279
|
+
DisconnectResponse,
|
|
3280
|
+
)
|
|
3281
|
+
|
|
3282
|
+
def stream_connection_state(
|
|
3283
|
+
self,
|
|
3284
|
+
) -> AsyncServerStream[StreamConnectionStateResponse]:
|
|
3285
|
+
"""Stream the connection state between the node hosting the API and its hub
|
|
3286
|
+
server. The current state is sent first, then a new message every time the
|
|
3287
|
+
state changes. The stream stays open until the caller closes it.
|
|
3288
|
+
"""
|
|
3289
|
+
return self._transport.server_stream(
|
|
3290
|
+
[Route("GET", "/v1/streams/hub-client/connection-state", "")],
|
|
3291
|
+
StreamConnectionStateRequest(),
|
|
3292
|
+
StreamConnectionStateResponse,
|
|
3293
|
+
)
|
|
3294
|
+
|
|
3295
|
+
|
|
3296
|
+
class AsyncHubServerServiceClient:
|
|
3297
|
+
"""A hub server is the control plane of a NanoPing setup: nodes authenticate with
|
|
3298
|
+
it, and every node on the same hub can find and manage the others. Use this
|
|
3299
|
+
service to list the nodes on the hub, follow them as they come and go, remove
|
|
3300
|
+
nodes, and approve or reject nodes that ask to join. The node hosting the API
|
|
3301
|
+
must host the hub server or be authenticated with one, otherwise calls fail with
|
|
3302
|
+
FailedPrecondition.
|
|
3303
|
+
"""
|
|
3304
|
+
|
|
3305
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3306
|
+
self._transport = transport
|
|
3307
|
+
|
|
3308
|
+
async def get_nodes(
|
|
3309
|
+
self,
|
|
3310
|
+
*,
|
|
3311
|
+
metadata_filters: Mapping[str, NodeMetadataItem] | None = None,
|
|
3312
|
+
service_filters: Sequence[NodeService] = (),
|
|
3313
|
+
) -> GetNodesResponse:
|
|
3314
|
+
"""Get the nodes authenticated with the hub server, optionally filtered.
|
|
3315
|
+
|
|
3316
|
+
Args:
|
|
3317
|
+
metadata_filters: Metadata filters keyed by metadata key. A node is
|
|
3318
|
+
included only if it has every key with an equal value of the same type.
|
|
3319
|
+
Leave empty to not filter by metadata.
|
|
3320
|
+
service_filters: Service filters. A node is included only if it offers
|
|
3321
|
+
every listed service. Leave empty to not filter by service.
|
|
3322
|
+
"""
|
|
3323
|
+
return await self._transport.unary(
|
|
3324
|
+
[Route("GET", "/v1/nodes", ""), Route("POST", "/v1/nodes/search", "*")],
|
|
3325
|
+
GetNodesRequest(
|
|
3326
|
+
metadata_filters=dict(metadata_filters or {}),
|
|
3327
|
+
service_filters=list(service_filters),
|
|
3328
|
+
),
|
|
3329
|
+
GetNodesResponse,
|
|
3330
|
+
)
|
|
3331
|
+
|
|
3332
|
+
async def remove_node(
|
|
3333
|
+
self,
|
|
3334
|
+
*,
|
|
3335
|
+
node_id: str = "",
|
|
3336
|
+
) -> RemoveNodeResponse:
|
|
3337
|
+
"""Remove a node from the hub server. This disconnects the node from the hub
|
|
3338
|
+
server and removes it from its networks.
|
|
3339
|
+
|
|
3340
|
+
Args:
|
|
3341
|
+
node_id: Id of the node to remove.
|
|
3342
|
+
"""
|
|
3343
|
+
return await self._transport.unary(
|
|
3344
|
+
[Route("DELETE", "/v1/nodes/{node_id}", "")],
|
|
3345
|
+
RemoveNodeRequest(node_id=node_id),
|
|
3346
|
+
RemoveNodeResponse,
|
|
3347
|
+
)
|
|
3348
|
+
|
|
3349
|
+
def stream_nodes(
|
|
3350
|
+
self,
|
|
3351
|
+
*,
|
|
3352
|
+
metadata_filters: Mapping[str, NodeMetadataItem] | None = None,
|
|
3353
|
+
service_filters: Sequence[NodeService] = (),
|
|
3354
|
+
) -> AsyncServerStream[StreamNodesResponse]:
|
|
3355
|
+
"""Stream the nodes authenticated with the hub server. The matching nodes are
|
|
3356
|
+
sent first, followed by an update every time a node is authenticated,
|
|
3357
|
+
deauthenticated, connects, disconnects or changes its details. Updates are
|
|
3358
|
+
not filtered. The stream stays open until the caller closes it.
|
|
3359
|
+
|
|
3360
|
+
Args:
|
|
3361
|
+
metadata_filters: Metadata filters keyed by metadata key. A node is
|
|
3362
|
+
included only if it has every key with an equal value of the same type.
|
|
3363
|
+
Leave empty to not filter by metadata.
|
|
3364
|
+
service_filters: Service filters. A node is included only if it offers
|
|
3365
|
+
every listed service. Leave empty to not filter by service.
|
|
3366
|
+
"""
|
|
3367
|
+
return self._transport.server_stream(
|
|
3368
|
+
[
|
|
3369
|
+
Route("GET", "/v1/streams/nodes", ""),
|
|
3370
|
+
Route("POST", "/v1/streams/nodes", "*"),
|
|
3371
|
+
],
|
|
3372
|
+
GetNodesRequest(
|
|
3373
|
+
metadata_filters=dict(metadata_filters or {}),
|
|
3374
|
+
service_filters=list(service_filters),
|
|
3375
|
+
),
|
|
3376
|
+
StreamNodesResponse,
|
|
3377
|
+
)
|
|
3378
|
+
|
|
3379
|
+
def authentication_by_requests(
|
|
3380
|
+
self,
|
|
3381
|
+
) -> AsyncBidiStream[AuthenticationByRequestAnswer, AuthenticationByRequestRequest]:
|
|
3382
|
+
"""Receive the authentication requests sent to the hub server on the node
|
|
3383
|
+
hosting the API, and accept or reject each one. Nothing is sent when the
|
|
3384
|
+
stream opens. A request is sent each time a node asks to authenticate, and
|
|
3385
|
+
the caller answers it by sending an answer for that request.
|
|
3386
|
+
"""
|
|
3387
|
+
return self._transport.bidi_stream(
|
|
3388
|
+
Route("POST", "/v1/streams/hub-server/authentication-requests", "*"),
|
|
3389
|
+
AuthenticationByRequestRequest,
|
|
3390
|
+
)
|
|
3391
|
+
|
|
3392
|
+
|
|
3393
|
+
class AsyncLoggingServiceClient:
|
|
3394
|
+
"""Every node keeps logs: its application log, and a log for each pipeline run,
|
|
3395
|
+
network and network instance. Use this service to follow a log live or to
|
|
3396
|
+
download a complete log file, from any node.
|
|
3397
|
+
"""
|
|
3398
|
+
|
|
3399
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3400
|
+
self._transport = transport
|
|
3401
|
+
|
|
3402
|
+
def open_log_stream(
|
|
3403
|
+
self,
|
|
3404
|
+
*,
|
|
3405
|
+
node_id: str = "",
|
|
3406
|
+
options: Options | None = None,
|
|
3407
|
+
app_log_stream_request: OpenAppLogStreamRequest | None = None,
|
|
3408
|
+
pipeline_run_log_stream_request: OpenPipelineRunLogStreamRequest | None = None,
|
|
3409
|
+
network_log_stream_request: LoggingOpenNetworkLogStreamRequest | None = None,
|
|
3410
|
+
network_instance_log_stream_request: LoggingOpenNetworkInstanceLogStreamRequest | None = None,
|
|
3411
|
+
) -> AsyncServerStream[Messages]:
|
|
3412
|
+
"""Stream the log messages of one log on a node. The requested number of past
|
|
3413
|
+
entries is sent first, then new entries as they are written. Fails with an
|
|
3414
|
+
invalid argument error when the node is invalid or no log is chosen, and ends
|
|
3415
|
+
with an error when the log cannot be read or the node loses its connection.
|
|
3416
|
+
|
|
3417
|
+
Args:
|
|
3418
|
+
node_id: ID of the node whose log to stream.
|
|
3419
|
+
options: Stream options. When unset, only new entries are sent.
|
|
3420
|
+
app_log_stream_request: Stream the node's application log.
|
|
3421
|
+
pipeline_run_log_stream_request: Stream the log of a pipeline run.
|
|
3422
|
+
network_log_stream_request: Stream the log of a network.
|
|
3423
|
+
network_instance_log_stream_request: Stream the log of a network
|
|
3424
|
+
instance.
|
|
3425
|
+
"""
|
|
3426
|
+
return self._transport.server_stream(
|
|
3427
|
+
[Route("POST", "/v1/streams/nodes/{node_id}/logs", "*")],
|
|
3428
|
+
LoggingOpenLogStreamRequest(
|
|
3429
|
+
node_id=node_id,
|
|
3430
|
+
options=options or Options(),
|
|
3431
|
+
app_log_stream_request=app_log_stream_request,
|
|
3432
|
+
pipeline_run_log_stream_request=pipeline_run_log_stream_request,
|
|
3433
|
+
network_log_stream_request=network_log_stream_request,
|
|
3434
|
+
network_instance_log_stream_request=network_instance_log_stream_request,
|
|
3435
|
+
),
|
|
3436
|
+
Messages,
|
|
3437
|
+
)
|
|
3438
|
+
|
|
3439
|
+
async def download_log_file(
|
|
3440
|
+
self,
|
|
3441
|
+
*,
|
|
3442
|
+
node_id: str = "",
|
|
3443
|
+
app_log_file_request: DownloadAppLogFileRequest | None = None,
|
|
3444
|
+
pipeline_run_log_file_request: DownloadPipelineRunLogFileRequest | None = None,
|
|
3445
|
+
network_log_file_request: DownloadNetworkLogFileRequest | None = None,
|
|
3446
|
+
network_instance_log_file_request: DownloadNetworkInstanceLogFileRequest | None = None,
|
|
3447
|
+
) -> str:
|
|
3448
|
+
"""Download one complete log file from a node as a series of chunks. Join the
|
|
3449
|
+
chunks in order to get the file. The stream ends when the whole file has been
|
|
3450
|
+
sent, or after an error chunk when the file could not be read.
|
|
3451
|
+
|
|
3452
|
+
Returns the whole file as text.
|
|
3453
|
+
|
|
3454
|
+
Args:
|
|
3455
|
+
node_id: ID of the node that holds the log file.
|
|
3456
|
+
app_log_file_request: Download the node's application log.
|
|
3457
|
+
pipeline_run_log_file_request: Download the log of a pipeline run.
|
|
3458
|
+
network_log_file_request: Download the log of a network.
|
|
3459
|
+
network_instance_log_file_request: Download the log of a network
|
|
3460
|
+
instance.
|
|
3461
|
+
"""
|
|
3462
|
+
return await self._transport.text(
|
|
3463
|
+
[Route("GET", "/v1/nodes/{node_id}/log-file", "")],
|
|
3464
|
+
DownloadLogFileRequest(
|
|
3465
|
+
node_id=node_id,
|
|
3466
|
+
app_log_file_request=app_log_file_request,
|
|
3467
|
+
pipeline_run_log_file_request=pipeline_run_log_file_request,
|
|
3468
|
+
network_log_file_request=network_log_file_request,
|
|
3469
|
+
network_instance_log_file_request=network_instance_log_file_request,
|
|
3470
|
+
),
|
|
3471
|
+
)
|
|
3472
|
+
|
|
3473
|
+
|
|
3474
|
+
class AsyncNetworkInstancesClient:
|
|
3475
|
+
"""A network instance is a network's presence on one node: the pipelines generated
|
|
3476
|
+
for that node from the network's blueprints. Instances are created, updated and
|
|
3477
|
+
removed automatically when their network changes, so they cannot be managed
|
|
3478
|
+
directly. Use this service to see which networks a node takes part in, follow its
|
|
3479
|
+
network pipelines, turn them on or off, and read their logs. The node needs
|
|
3480
|
+
pipelines enabled.
|
|
3481
|
+
"""
|
|
3482
|
+
|
|
3483
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3484
|
+
self._transport = transport
|
|
3485
|
+
|
|
3486
|
+
async def get_network_instances(
|
|
3487
|
+
self,
|
|
3488
|
+
*,
|
|
3489
|
+
node_id: str = "",
|
|
3490
|
+
) -> GetNetworkInstancesResponse:
|
|
3491
|
+
"""Get all network instances on a node, each with its pipelines.
|
|
3492
|
+
|
|
3493
|
+
Args:
|
|
3494
|
+
node_id: The ID of the node to fetch network instances from.
|
|
3495
|
+
"""
|
|
3496
|
+
return await self._transport.unary(
|
|
3497
|
+
[Route("GET", "/v1/nodes/{node_id}/network-instances", "")],
|
|
3498
|
+
GetNetworkInstancesRequest(node_id=node_id),
|
|
3499
|
+
GetNetworkInstancesResponse,
|
|
3500
|
+
)
|
|
3501
|
+
|
|
3502
|
+
def stream_network_instances(
|
|
3503
|
+
self,
|
|
3504
|
+
*,
|
|
3505
|
+
node_id: str = "",
|
|
3506
|
+
) -> AsyncServerStream[StreamNetworkInstanceEvent]:
|
|
3507
|
+
"""Stream changes to the network instances on a node. Nothing is sent when the
|
|
3508
|
+
stream opens; an event is sent each time an instance is created, updated or
|
|
3509
|
+
deleted, and an update is also sent when one of its pipelines changes. The
|
|
3510
|
+
stream ends if the connection to the node is lost.
|
|
3511
|
+
|
|
3512
|
+
Args:
|
|
3513
|
+
node_id: The ID of the node to stream network instances from.
|
|
3514
|
+
"""
|
|
3515
|
+
return self._transport.server_stream(
|
|
3516
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/network-instances", "")],
|
|
3517
|
+
StreamNetworkInstancesRequest(node_id=node_id),
|
|
3518
|
+
StreamNetworkInstanceEvent,
|
|
3519
|
+
)
|
|
3520
|
+
|
|
3521
|
+
async def get_network_pipelines(
|
|
3522
|
+
self,
|
|
3523
|
+
*,
|
|
3524
|
+
node_id: str = "",
|
|
3525
|
+
optional_network_id: str | None = None,
|
|
3526
|
+
optional_instance_id: str | None = None,
|
|
3527
|
+
optional_blueprint_id: str | None = None,
|
|
3528
|
+
) -> GetNetworkPipelinesResponse:
|
|
3529
|
+
"""Get the network instance pipelines on a node, optionally filtered. A pipeline
|
|
3530
|
+
must match every filter that is set.
|
|
3531
|
+
|
|
3532
|
+
Args:
|
|
3533
|
+
node_id: The ID of the node to fetch network instance pipelines from.
|
|
3534
|
+
optional_network_id: Only return pipelines belonging to this network ID.
|
|
3535
|
+
optional_instance_id: Only return pipelines belonging to this network
|
|
3536
|
+
instance ID.
|
|
3537
|
+
optional_blueprint_id: Only return pipelines generated from this
|
|
3538
|
+
blueprint ID.
|
|
3539
|
+
"""
|
|
3540
|
+
return await self._transport.unary(
|
|
3541
|
+
[Route("GET", "/v1/nodes/{node_id}/network-pipelines", "")],
|
|
3542
|
+
GetNetworkPipelinesRequest(
|
|
3543
|
+
node_id=node_id,
|
|
3544
|
+
optional_network_id=optional_network_id,
|
|
3545
|
+
optional_instance_id=optional_instance_id,
|
|
3546
|
+
optional_blueprint_id=optional_blueprint_id,
|
|
3547
|
+
),
|
|
3548
|
+
GetNetworkPipelinesResponse,
|
|
3549
|
+
)
|
|
3550
|
+
|
|
3551
|
+
def stream_network_pipelines(
|
|
3552
|
+
self,
|
|
3553
|
+
*,
|
|
3554
|
+
node_id: str = "",
|
|
3555
|
+
) -> AsyncServerStream[StreamNetworkPipelineEvent]:
|
|
3556
|
+
"""Stream changes to the network instance pipelines on a node. Nothing is sent
|
|
3557
|
+
when the stream opens; an event is sent each time a pipeline is created,
|
|
3558
|
+
updated or deleted. The stream ends if the connection to the node is lost.
|
|
3559
|
+
|
|
3560
|
+
Args:
|
|
3561
|
+
node_id: The ID of the node to stream network instance pipelines from.
|
|
3562
|
+
"""
|
|
3563
|
+
return self._transport.server_stream(
|
|
3564
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/network-pipelines", "")],
|
|
3565
|
+
StreamNetworkPipelinesRequest(node_id=node_id),
|
|
3566
|
+
StreamNetworkPipelineEvent,
|
|
3567
|
+
)
|
|
3568
|
+
|
|
3569
|
+
async def toggle_network_pipeline(
|
|
3570
|
+
self,
|
|
3571
|
+
*,
|
|
3572
|
+
node_id: str = "",
|
|
3573
|
+
optional_pipeline_id: str | None = None,
|
|
3574
|
+
optional_instance_pipeline_id: str | None = None,
|
|
3575
|
+
) -> ToggleNetworkPipelineResponse:
|
|
3576
|
+
"""Enable or disable a network instance pipeline on a node, which starts or
|
|
3577
|
+
stops the pipeline. Each call flips the current state. Fails with a not found
|
|
3578
|
+
error if no matching pipeline exists.
|
|
3579
|
+
|
|
3580
|
+
Args:
|
|
3581
|
+
node_id: The ID of the node the pipeline runs on.
|
|
3582
|
+
optional_pipeline_id: The pipeline's `pipeline_id`.
|
|
3583
|
+
optional_instance_pipeline_id: The pipeline's `id`.
|
|
3584
|
+
"""
|
|
3585
|
+
return await self._transport.unary(
|
|
3586
|
+
[Route("POST", "/v1/nodes/{node_id}/network-pipelines/toggle", "*")],
|
|
3587
|
+
ToggleNetworkPipelineRequest(
|
|
3588
|
+
node_id=node_id,
|
|
3589
|
+
optional_pipeline_id=optional_pipeline_id,
|
|
3590
|
+
optional_instance_pipeline_id=optional_instance_pipeline_id,
|
|
3591
|
+
),
|
|
3592
|
+
ToggleNetworkPipelineResponse,
|
|
3593
|
+
)
|
|
3594
|
+
|
|
3595
|
+
def open_log_stream(
|
|
3596
|
+
self,
|
|
3597
|
+
*,
|
|
3598
|
+
node_id: str = "",
|
|
3599
|
+
network_instance_id: str = "",
|
|
3600
|
+
options: Options | None = None,
|
|
3601
|
+
) -> AsyncServerStream[NetworkInstanceLogStreamMessages]:
|
|
3602
|
+
"""Stream the log messages of a network instance on a node. The requested number
|
|
3603
|
+
of past lines is sent first, then new messages as they are logged, until the
|
|
3604
|
+
connection to the node is lost.
|
|
3605
|
+
|
|
3606
|
+
Args:
|
|
3607
|
+
node_id: The ID of the node the network instance runs on.
|
|
3608
|
+
network_instance_id: The ID of the network instance whose log to stream.
|
|
3609
|
+
options: Log stream options, such as how many past lines to send first.
|
|
3610
|
+
"""
|
|
3611
|
+
return self._transport.server_stream(
|
|
3612
|
+
[
|
|
3613
|
+
Route("GET", "/v1/streams/nodes/{node_id}/network-instances/{network_instance_id}/logs", ""),
|
|
3614
|
+
],
|
|
3615
|
+
NetworksOpenNetworkInstanceLogStreamRequest(
|
|
3616
|
+
node_id=node_id,
|
|
3617
|
+
network_instance_id=network_instance_id,
|
|
3618
|
+
options=options or Options(),
|
|
3619
|
+
),
|
|
3620
|
+
NetworkInstanceLogStreamMessages,
|
|
3621
|
+
)
|
|
3622
|
+
|
|
3623
|
+
|
|
3624
|
+
class AsyncNetworksClient:
|
|
3625
|
+
"""A network is a virtual network that connects nodes as if they shared a local
|
|
3626
|
+
network, giving each node its own IP address. All traffic flows through a central
|
|
3627
|
+
relay node. When a network is created or changed, the pipelines each node needs
|
|
3628
|
+
are generated from the network's blueprints and deployed automatically. Use this
|
|
3629
|
+
service to create and change networks and to follow their changes and logs.
|
|
3630
|
+
Networks are stored on the connected node that has networks enabled, and calls
|
|
3631
|
+
wait until that node is connected.
|
|
3632
|
+
"""
|
|
3633
|
+
|
|
3634
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3635
|
+
self._transport = transport
|
|
3636
|
+
|
|
3637
|
+
async def get_network(
|
|
3638
|
+
self,
|
|
3639
|
+
*,
|
|
3640
|
+
id: str = "",
|
|
3641
|
+
) -> GetNetworkResponse:
|
|
3642
|
+
"""Get a single network.
|
|
3643
|
+
|
|
3644
|
+
Args:
|
|
3645
|
+
id: The ID of the network to fetch.
|
|
3646
|
+
"""
|
|
3647
|
+
return await self._transport.unary(
|
|
3648
|
+
[Route("GET", "/v1/networks/{id}", "")],
|
|
3649
|
+
GetNetworkRequest(id=id),
|
|
3650
|
+
GetNetworkResponse,
|
|
3651
|
+
)
|
|
3652
|
+
|
|
3653
|
+
async def get_networks(self) -> GetNetworksResponse:
|
|
3654
|
+
"""Get all networks."""
|
|
3655
|
+
return await self._transport.unary(
|
|
3656
|
+
[Route("GET", "/v1/networks", "")],
|
|
3657
|
+
GetNetworksRequest(),
|
|
3658
|
+
GetNetworksResponse,
|
|
3659
|
+
)
|
|
3660
|
+
|
|
3661
|
+
async def create_network(
|
|
3662
|
+
self,
|
|
3663
|
+
*,
|
|
3664
|
+
network: Network | None = None,
|
|
3665
|
+
) -> CreateNetworkResponse:
|
|
3666
|
+
"""Create a network and return it. Every connected node is added to the network
|
|
3667
|
+
automatically and assigned the first free IP address in its subnet, so nodes
|
|
3668
|
+
given in the request are ignored.
|
|
3669
|
+
|
|
3670
|
+
Args:
|
|
3671
|
+
network: The network to create. Required.
|
|
3672
|
+
"""
|
|
3673
|
+
return await self._transport.unary(
|
|
3674
|
+
[Route("POST", "/v1/networks", "network")],
|
|
3675
|
+
CreateNetworkRequest(network=network or Network()),
|
|
3676
|
+
CreateNetworkResponse,
|
|
3677
|
+
)
|
|
3678
|
+
|
|
3679
|
+
async def update_network(
|
|
3680
|
+
self,
|
|
3681
|
+
*,
|
|
3682
|
+
id: str = "",
|
|
3683
|
+
network: Network | None = None,
|
|
3684
|
+
) -> UpdateNetworkResponse:
|
|
3685
|
+
"""Replace the settings of an existing network and return the updated network.
|
|
3686
|
+
Nodes cannot be added or removed, and their IP address and role cannot be
|
|
3687
|
+
changed.
|
|
3688
|
+
|
|
3689
|
+
Args:
|
|
3690
|
+
id: The ID of the network to update.
|
|
3691
|
+
network: The new settings of the network. Required. All fields replace
|
|
3692
|
+
the current values, except `nodes`: leave it empty to keep the nodes
|
|
3693
|
+
unchanged, or list every current node to edit their carriers and
|
|
3694
|
+
parameters.
|
|
3695
|
+
"""
|
|
3696
|
+
return await self._transport.unary(
|
|
3697
|
+
[Route("PUT", "/v1/networks/{id}", "network")],
|
|
3698
|
+
UpdateNetworkRequest(id=id, network=network or Network()),
|
|
3699
|
+
UpdateNetworkResponse,
|
|
3700
|
+
)
|
|
3701
|
+
|
|
3702
|
+
async def delete_network(
|
|
3703
|
+
self,
|
|
3704
|
+
*,
|
|
3705
|
+
id: str = "",
|
|
3706
|
+
) -> DeleteNetworkResponse:
|
|
3707
|
+
"""Delete a network.
|
|
3708
|
+
|
|
3709
|
+
Args:
|
|
3710
|
+
id: The ID of the network to delete.
|
|
3711
|
+
"""
|
|
3712
|
+
return await self._transport.unary(
|
|
3713
|
+
[Route("DELETE", "/v1/networks/{id}", "")],
|
|
3714
|
+
DeleteNetworkRequest(id=id),
|
|
3715
|
+
DeleteNetworkResponse,
|
|
3716
|
+
)
|
|
3717
|
+
|
|
3718
|
+
def stream_networks(self) -> AsyncServerStream[StreamNetworksEvent]:
|
|
3719
|
+
"""Stream changes to networks. Nothing is sent when the stream opens; an event
|
|
3720
|
+
is sent each time a network is created, updated or deleted. The stream ends
|
|
3721
|
+
if the connection to the networks node is lost.
|
|
3722
|
+
"""
|
|
3723
|
+
return self._transport.server_stream(
|
|
3724
|
+
[Route("GET", "/v1/streams/networks", "")],
|
|
3725
|
+
StreamNetworksRequest(),
|
|
3726
|
+
StreamNetworksEvent,
|
|
3727
|
+
)
|
|
3728
|
+
|
|
3729
|
+
def open_log_stream(
|
|
3730
|
+
self,
|
|
3731
|
+
*,
|
|
3732
|
+
network_id: str = "",
|
|
3733
|
+
options: Options | None = None,
|
|
3734
|
+
) -> AsyncServerStream[NetworkLogStreamMessages]:
|
|
3735
|
+
"""Stream the log messages of a network. The requested number of past lines is
|
|
3736
|
+
sent first, then new messages as they are logged, until the connection to the
|
|
3737
|
+
networks node is lost.
|
|
3738
|
+
|
|
3739
|
+
Args:
|
|
3740
|
+
network_id: The ID of the network whose log to stream.
|
|
3741
|
+
options: Log stream options, such as how many past lines to send first.
|
|
3742
|
+
"""
|
|
3743
|
+
return self._transport.server_stream(
|
|
3744
|
+
[Route("GET", "/v1/streams/networks/{network_id}/logs", "")],
|
|
3745
|
+
NetworksOpenNetworkLogStreamRequest(
|
|
3746
|
+
network_id=network_id,
|
|
3747
|
+
options=options or Options(),
|
|
3748
|
+
),
|
|
3749
|
+
NetworkLogStreamMessages,
|
|
3750
|
+
)
|
|
3751
|
+
|
|
3752
|
+
|
|
3753
|
+
class AsyncPipelinesServiceClient:
|
|
3754
|
+
"""A pipeline is the configuration a node runs to move traffic, connecting
|
|
3755
|
+
components such as UDP sockets, TUN interfaces and error correction encoders into
|
|
3756
|
+
a data flow. Each start of a pipeline creates a new run, with its own logs and
|
|
3757
|
+
telemetry. Use this service to create, change, start and stop pipelines on any
|
|
3758
|
+
node, and to follow their changes, logs and telemetry.
|
|
3759
|
+
"""
|
|
3760
|
+
|
|
3761
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
3762
|
+
self._transport = transport
|
|
3763
|
+
|
|
3764
|
+
async def get_pipelines(
|
|
3765
|
+
self,
|
|
3766
|
+
*,
|
|
3767
|
+
node_id: str = "",
|
|
3768
|
+
) -> GetPipelinesResponse:
|
|
3769
|
+
"""Lists all pipelines on the node.
|
|
3770
|
+
|
|
3771
|
+
Args:
|
|
3772
|
+
node_id: ID of the node to list the pipelines of.
|
|
3773
|
+
"""
|
|
3774
|
+
return await self._transport.unary(
|
|
3775
|
+
[Route("GET", "/v1/nodes/{node_id}/pipelines", "")],
|
|
3776
|
+
GetPipelinesRequest(node_id=node_id),
|
|
3777
|
+
GetPipelinesResponse,
|
|
3778
|
+
)
|
|
3779
|
+
|
|
3780
|
+
async def get_pipeline_by_id(
|
|
3781
|
+
self,
|
|
3782
|
+
*,
|
|
3783
|
+
node_id: str = "",
|
|
3784
|
+
id: str = "",
|
|
3785
|
+
) -> GetPipelineByIdResponse:
|
|
3786
|
+
"""Get one pipeline. Fails with a not found error if it does not exist.
|
|
3787
|
+
|
|
3788
|
+
Args:
|
|
3789
|
+
node_id: ID of the node that hosts the pipeline.
|
|
3790
|
+
id: ID of the pipeline.
|
|
3791
|
+
"""
|
|
3792
|
+
return await self._transport.unary(
|
|
3793
|
+
[Route("GET", "/v1/nodes/{node_id}/pipelines/{id}", "")],
|
|
3794
|
+
GetPipelineByIdRequest(node_id=node_id, id=id),
|
|
3795
|
+
GetPipelineByIdResponse,
|
|
3796
|
+
)
|
|
3797
|
+
|
|
3798
|
+
async def get_pipeline_by_name(
|
|
3799
|
+
self,
|
|
3800
|
+
*,
|
|
3801
|
+
node_id: str = "",
|
|
3802
|
+
name: str = "",
|
|
3803
|
+
) -> GetPipelineByNameResponse:
|
|
3804
|
+
"""Get one pipeline by name. Fails with a not found error if no pipeline, or
|
|
3805
|
+
more than one, has that name.
|
|
3806
|
+
|
|
3807
|
+
Args:
|
|
3808
|
+
node_id: ID of the node that hosts the pipeline.
|
|
3809
|
+
name: Exact name of the pipeline. Example: `UDP tunnel`
|
|
3810
|
+
"""
|
|
3811
|
+
return await self._transport.unary(
|
|
3812
|
+
[Route("GET", "/v1/nodes/{node_id}/pipelines-by-name/{name}", "")],
|
|
3813
|
+
GetPipelineByNameRequest(node_id=node_id, name=name),
|
|
3814
|
+
GetPipelineByNameResponse,
|
|
3815
|
+
)
|
|
3816
|
+
|
|
3817
|
+
async def get_pipeline_by_run_id(
|
|
3818
|
+
self,
|
|
3819
|
+
*,
|
|
3820
|
+
node_id: str = "",
|
|
3821
|
+
id: str = "",
|
|
3822
|
+
) -> GetPipelineByRunIdResponse:
|
|
3823
|
+
"""Get the pipeline that a run belongs to. An unknown run fails with a timeout
|
|
3824
|
+
error.
|
|
3825
|
+
|
|
3826
|
+
Args:
|
|
3827
|
+
node_id: ID of the node that hosts the pipeline.
|
|
3828
|
+
id: ID of the run.
|
|
3829
|
+
"""
|
|
3830
|
+
return await self._transport.unary(
|
|
3831
|
+
[Route("GET", "/v1/nodes/{node_id}/pipeline-runs/{id}", "")],
|
|
3832
|
+
GetPipelineByRunIdRequest(node_id=node_id, id=id),
|
|
3833
|
+
GetPipelineByRunIdResponse,
|
|
3834
|
+
)
|
|
3835
|
+
|
|
3836
|
+
async def create_pipeline(
|
|
3837
|
+
self,
|
|
3838
|
+
*,
|
|
3839
|
+
node_id: str = "",
|
|
3840
|
+
name: str = "",
|
|
3841
|
+
json_config: str = "",
|
|
3842
|
+
restart_policy: RestartPolicy | None = None,
|
|
3843
|
+
startup_policy: StartupPolicy | None = None,
|
|
3844
|
+
default_logging_level: Level | None = None,
|
|
3845
|
+
node_reference_id: str | None = None,
|
|
3846
|
+
instructions_timeout: int | None = None,
|
|
3847
|
+
cpu_pin: int | None = None,
|
|
3848
|
+
performance_mode: bool | None = None,
|
|
3849
|
+
) -> CreatePipelineResponse:
|
|
3850
|
+
"""Create a pipeline from a JSON configuration and return it. The pipeline is
|
|
3851
|
+
not started. Fails with an invalid argument error if the configuration is
|
|
3852
|
+
invalid or the CPU pin is not a thread of the node.
|
|
3853
|
+
|
|
3854
|
+
Args:
|
|
3855
|
+
node_id: ID of the node to create the pipeline on.
|
|
3856
|
+
name: Name of the pipeline. Example: `UDP tunnel`
|
|
3857
|
+
json_config: The pipeline configuration as a JSON string.
|
|
3858
|
+
restart_policy: The restart policy of the pipeline. Leave unset to never
|
|
3859
|
+
restart.
|
|
3860
|
+
startup_policy: The startup policy of the pipeline. Leave unset to start
|
|
3861
|
+
it manually only.
|
|
3862
|
+
default_logging_level: The default logging level.
|
|
3863
|
+
node_reference_id: ID of the related node.
|
|
3864
|
+
instructions_timeout: The timeout in seconds. Must be greater than 0.
|
|
3865
|
+
Example: `30`
|
|
3866
|
+
cpu_pin: Zero indexed CPU thread number. Must be lower than the node's
|
|
3867
|
+
thread count.
|
|
3868
|
+
performance_mode: True to run the pinned thread in performance mode.
|
|
3869
|
+
"""
|
|
3870
|
+
return await self._transport.unary(
|
|
3871
|
+
[Route("POST", "/v1/nodes/{node_id}/pipelines", "*")],
|
|
3872
|
+
CreatePipelineRequest(
|
|
3873
|
+
node_id=node_id,
|
|
3874
|
+
name=name,
|
|
3875
|
+
json_config=json_config,
|
|
3876
|
+
restart_policy=restart_policy or RestartPolicy(),
|
|
3877
|
+
startup_policy=startup_policy or StartupPolicy(),
|
|
3878
|
+
default_logging_level=default_logging_level,
|
|
3879
|
+
node_reference_id=node_reference_id,
|
|
3880
|
+
instructions_timeout=instructions_timeout,
|
|
3881
|
+
cpu_pin=cpu_pin,
|
|
3882
|
+
performance_mode=performance_mode,
|
|
3883
|
+
),
|
|
3884
|
+
CreatePipelineResponse,
|
|
3885
|
+
)
|
|
3886
|
+
|
|
3887
|
+
async def update_pipeline(
|
|
3888
|
+
self,
|
|
3889
|
+
*,
|
|
3890
|
+
node_id: str = "",
|
|
3891
|
+
id: str = "",
|
|
3892
|
+
name: str = "",
|
|
3893
|
+
json_config: str = "",
|
|
3894
|
+
restart_policy: RestartPolicy | None = None,
|
|
3895
|
+
startup_policy: StartupPolicy | None = None,
|
|
3896
|
+
default_logging_level: Level = Level.STATE,
|
|
3897
|
+
instructions_timeout: int = 0,
|
|
3898
|
+
cpu_pin: int | None = None,
|
|
3899
|
+
performance_mode: bool | None = None,
|
|
3900
|
+
node_reference_id: str | None = None,
|
|
3901
|
+
force_restart: bool = False,
|
|
3902
|
+
) -> UpdatePipelineResponse:
|
|
3903
|
+
"""Replace the settings of a pipeline and return the updated pipeline. If the
|
|
3904
|
+
pipeline is running and its configuration changed, the new configuration is
|
|
3905
|
+
applied to the current run. If that is not possible, the call fails because
|
|
3906
|
+
the pipeline is running, unless a restart is forced.
|
|
3907
|
+
|
|
3908
|
+
Args:
|
|
3909
|
+
node_id: ID of the node that hosts the pipeline.
|
|
3910
|
+
id: ID of the pipeline to update.
|
|
3911
|
+
name: New name of the pipeline. Example: `UDP tunnel`
|
|
3912
|
+
json_config: New pipeline configuration as a JSON string.
|
|
3913
|
+
restart_policy: New restart policy of the pipeline. Unset means never
|
|
3914
|
+
restart.
|
|
3915
|
+
startup_policy: New startup policy of the pipeline. Unset means start
|
|
3916
|
+
manually only.
|
|
3917
|
+
default_logging_level: New default logging level of the pipeline. Unset
|
|
3918
|
+
means `STATE`, not the `INFO` default used on create.
|
|
3919
|
+
instructions_timeout: New time in seconds before a pipeline instruction
|
|
3920
|
+
is considered timed out. Must be greater than 0. Example: `30`
|
|
3921
|
+
cpu_pin: Zero indexed CPU thread number. Must be lower than the node's
|
|
3922
|
+
thread count.
|
|
3923
|
+
performance_mode: True to run the pinned thread in performance mode.
|
|
3924
|
+
node_reference_id: ID of the related node.
|
|
3925
|
+
force_restart: If true and the pipeline is running, the pipeline is
|
|
3926
|
+
restarted when the new configuration cannot be applied to the current
|
|
3927
|
+
run. The call then returns once the new run is running.
|
|
3928
|
+
"""
|
|
3929
|
+
return await self._transport.unary(
|
|
3930
|
+
[Route("PUT", "/v1/nodes/{node_id}/pipelines/{id}", "*")],
|
|
3931
|
+
UpdatePipelineRequest(
|
|
3932
|
+
node_id=node_id,
|
|
3933
|
+
id=id,
|
|
3934
|
+
name=name,
|
|
3935
|
+
json_config=json_config,
|
|
3936
|
+
restart_policy=restart_policy or RestartPolicy(),
|
|
3937
|
+
startup_policy=startup_policy or StartupPolicy(),
|
|
3938
|
+
default_logging_level=default_logging_level,
|
|
3939
|
+
instructions_timeout=instructions_timeout,
|
|
3940
|
+
cpu_pin=cpu_pin,
|
|
3941
|
+
performance_mode=performance_mode,
|
|
3942
|
+
node_reference_id=node_reference_id,
|
|
3943
|
+
force_restart=force_restart,
|
|
3944
|
+
),
|
|
3945
|
+
UpdatePipelineResponse,
|
|
3946
|
+
)
|
|
3947
|
+
|
|
3948
|
+
async def delete_pipeline(
|
|
3949
|
+
self,
|
|
3950
|
+
*,
|
|
3951
|
+
node_id: str = "",
|
|
3952
|
+
id: str = "",
|
|
3953
|
+
) -> DeletePipelineResponse:
|
|
3954
|
+
"""Delete a pipeline. Fails with a not found error if it does not exist.
|
|
3955
|
+
|
|
3956
|
+
Args:
|
|
3957
|
+
node_id: ID of the node that hosts the pipeline.
|
|
3958
|
+
id: ID of the pipeline to delete.
|
|
3959
|
+
"""
|
|
3960
|
+
return await self._transport.unary(
|
|
3961
|
+
[Route("DELETE", "/v1/nodes/{node_id}/pipelines/{id}", "")],
|
|
3962
|
+
DeletePipelineRequest(node_id=node_id, id=id),
|
|
3963
|
+
DeletePipelineResponse,
|
|
3964
|
+
)
|
|
3965
|
+
|
|
3966
|
+
async def start_pipeline(
|
|
3967
|
+
self,
|
|
3968
|
+
*,
|
|
3969
|
+
node_id: str = "",
|
|
3970
|
+
id: str | None = None,
|
|
3971
|
+
name: str | None = None,
|
|
3972
|
+
) -> StartPipelineResponse:
|
|
3973
|
+
"""Start a pipeline and return its new run once it is running. Fails if the
|
|
3974
|
+
pipeline is unknown, already started, or does not reach the running state
|
|
3975
|
+
within 10 seconds.
|
|
3976
|
+
|
|
3977
|
+
Args:
|
|
3978
|
+
node_id: ID of the node that hosts the pipeline.
|
|
3979
|
+
id: ID of the pipeline.
|
|
3980
|
+
name: Exact name of the pipeline. Fails if more than one pipeline has
|
|
3981
|
+
this name. Example: `UDP tunnel`
|
|
3982
|
+
"""
|
|
3983
|
+
return await self._transport.unary(
|
|
3984
|
+
[
|
|
3985
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines/{id}/start", ""),
|
|
3986
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines-by-name/{name}/start", ""),
|
|
3987
|
+
],
|
|
3988
|
+
StartPipelineRequest(node_id=node_id, id=id, name=name),
|
|
3989
|
+
StartPipelineResponse,
|
|
3990
|
+
)
|
|
3991
|
+
|
|
3992
|
+
async def stop_pipeline(
|
|
3993
|
+
self,
|
|
3994
|
+
*,
|
|
3995
|
+
node_id: str = "",
|
|
3996
|
+
id: str | None = None,
|
|
3997
|
+
name: str | None = None,
|
|
3998
|
+
run_id: str | None = None,
|
|
3999
|
+
) -> StopPipelineResponse:
|
|
4000
|
+
"""Stop a pipeline, found by its ID, its name or its current run. Returns once
|
|
4001
|
+
the stop is requested, without waiting for the run to end. Fails if the
|
|
4002
|
+
pipeline is unknown or already stopped.
|
|
4003
|
+
|
|
4004
|
+
Args:
|
|
4005
|
+
node_id: ID of the node that hosts the pipeline.
|
|
4006
|
+
id: ID of the pipeline.
|
|
4007
|
+
name: Exact name of the pipeline. Fails if more than one pipeline has
|
|
4008
|
+
this name. Example: `UDP tunnel`
|
|
4009
|
+
run_id: ID of the pipeline's current run.
|
|
4010
|
+
"""
|
|
4011
|
+
return await self._transport.unary(
|
|
4012
|
+
[
|
|
4013
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines/{id}/stop", ""),
|
|
4014
|
+
Route("POST", "/v1/nodes/{node_id}/pipelines-by-name/{name}/stop", ""),
|
|
4015
|
+
Route("POST", "/v1/nodes/{node_id}/pipeline-runs/{run_id}/stop", ""),
|
|
4016
|
+
],
|
|
4017
|
+
StopPipelineRequest(node_id=node_id, id=id, name=name, run_id=run_id),
|
|
4018
|
+
StopPipelineResponse,
|
|
4019
|
+
)
|
|
4020
|
+
|
|
4021
|
+
def stream_pipelines(
|
|
4022
|
+
self,
|
|
4023
|
+
*,
|
|
4024
|
+
node_id: str = "",
|
|
4025
|
+
) -> AsyncServerStream[StreamPipelinesEvent]:
|
|
4026
|
+
"""Stream changes to the pipelines of a node. Nothing is sent when the stream
|
|
4027
|
+
opens, so get the pipelines first for the current list. An event is sent each
|
|
4028
|
+
time a pipeline is created, updated or deleted, and when a pipeline starts or
|
|
4029
|
+
stops.
|
|
4030
|
+
|
|
4031
|
+
Args:
|
|
4032
|
+
node_id: ID of the node to stream pipeline changes from.
|
|
4033
|
+
"""
|
|
4034
|
+
return self._transport.server_stream(
|
|
4035
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/pipelines", "")],
|
|
4036
|
+
StreamPipelinesRequest(node_id=node_id),
|
|
4037
|
+
StreamPipelinesEvent,
|
|
4038
|
+
)
|
|
4039
|
+
|
|
4040
|
+
def open_log_stream(
|
|
4041
|
+
self,
|
|
4042
|
+
*,
|
|
4043
|
+
node_id: str = "",
|
|
4044
|
+
run_id: str = "",
|
|
4045
|
+
options: Options | None = None,
|
|
4046
|
+
) -> AsyncServerStream[LogStreamMessages]:
|
|
4047
|
+
"""Stream the log messages of a pipeline run. The requested number of past lines
|
|
4048
|
+
is sent first, then new messages as they are logged.
|
|
4049
|
+
|
|
4050
|
+
Args:
|
|
4051
|
+
node_id: ID of the node that hosts the run.
|
|
4052
|
+
run_id: ID of the run to stream logs from.
|
|
4053
|
+
options: Stream options, such as how many past lines to send first.
|
|
4054
|
+
Leave unset to receive only new messages.
|
|
4055
|
+
"""
|
|
4056
|
+
return self._transport.server_stream(
|
|
4057
|
+
[
|
|
4058
|
+
Route("GET", "/v1/streams/nodes/{node_id}/pipeline-runs/{run_id}/logs", ""),
|
|
4059
|
+
],
|
|
4060
|
+
PipelineOpenLogStreamRequest(
|
|
4061
|
+
node_id=node_id,
|
|
4062
|
+
run_id=run_id,
|
|
4063
|
+
options=options or Options(),
|
|
4064
|
+
),
|
|
4065
|
+
LogStreamMessages,
|
|
4066
|
+
)
|
|
4067
|
+
|
|
4068
|
+
def open_telemetry_stream(
|
|
4069
|
+
self,
|
|
4070
|
+
*,
|
|
4071
|
+
node_id: str = "",
|
|
4072
|
+
run_id: str = "",
|
|
4073
|
+
) -> AsyncServerStream[TelemetrySample]:
|
|
4074
|
+
"""Streams telemetry samples (metrics and KPI values) of a pipeline run at
|
|
4075
|
+
regular intervals while the run is active. The stream ends with an error when
|
|
4076
|
+
the run stops, when the run is unknown, or when the node disconnects.
|
|
4077
|
+
|
|
4078
|
+
Args:
|
|
4079
|
+
node_id: ID of the node that hosts the run.
|
|
4080
|
+
run_id: ID of the run to stream telemetry from.
|
|
4081
|
+
"""
|
|
4082
|
+
return self._transport.server_stream(
|
|
4083
|
+
[
|
|
4084
|
+
Route("GET", "/v1/streams/nodes/{node_id}/pipeline-runs/{run_id}/telemetry", ""),
|
|
4085
|
+
],
|
|
4086
|
+
OpenTelemetryStreamRequest(node_id=node_id, run_id=run_id),
|
|
4087
|
+
TelemetrySample,
|
|
4088
|
+
)
|
|
4089
|
+
|
|
4090
|
+
|
|
4091
|
+
class AsyncResourcesServiceClient:
|
|
4092
|
+
"""Live system information of a node: resource metrics such as CPU, memory, storage
|
|
4093
|
+
and network interface usage, and the network flows crossing its interfaces. Use
|
|
4094
|
+
this service to monitor the health and traffic of any node.
|
|
4095
|
+
"""
|
|
4096
|
+
|
|
4097
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
4098
|
+
self._transport = transport
|
|
4099
|
+
|
|
4100
|
+
def open_metrics_stream(
|
|
4101
|
+
self,
|
|
4102
|
+
*,
|
|
4103
|
+
node_id: str = "",
|
|
4104
|
+
) -> AsyncServerStream[MetricsSample]:
|
|
4105
|
+
"""Stream the resource metrics of a node, such as CPU, memory, disk and network
|
|
4106
|
+
interface usage. A sample of the current metrics is sent when the stream
|
|
4107
|
+
opens. The stream stays open until the client closes it, and ends with an
|
|
4108
|
+
error if the node loses its connection.
|
|
4109
|
+
|
|
4110
|
+
Args:
|
|
4111
|
+
node_id: ID of the node to read metrics from.
|
|
4112
|
+
"""
|
|
4113
|
+
return self._transport.server_stream(
|
|
4114
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/metrics", "")],
|
|
4115
|
+
OpenMetricsStreamRequest(node_id=node_id),
|
|
4116
|
+
MetricsSample,
|
|
4117
|
+
)
|
|
4118
|
+
|
|
4119
|
+
def open_flows_stream(
|
|
4120
|
+
self,
|
|
4121
|
+
*,
|
|
4122
|
+
node_id: str = "",
|
|
4123
|
+
) -> AsyncServerStream[FlowsSample]:
|
|
4124
|
+
"""Stream a snapshot of the network flows crossing the interfaces of a node,
|
|
4125
|
+
about once a second, starting right away. The node only captures packets
|
|
4126
|
+
while someone watches its flows, so the first samples may be empty or
|
|
4127
|
+
incomplete.
|
|
4128
|
+
|
|
4129
|
+
Args:
|
|
4130
|
+
node_id: ID of the node to read flows from.
|
|
4131
|
+
"""
|
|
4132
|
+
return self._transport.server_stream(
|
|
4133
|
+
[Route("GET", "/v1/streams/nodes/{node_id}/flows", "")],
|
|
4134
|
+
OpenFlowsStreamRequest(node_id=node_id),
|
|
4135
|
+
FlowsSample,
|
|
4136
|
+
)
|
|
4137
|
+
|
|
4138
|
+
|
|
4139
|
+
class _Services:
|
|
4140
|
+
blueprints: BlueprintsClient
|
|
4141
|
+
config: ConfigServiceClient
|
|
4142
|
+
hub_client: HubClientServiceClient
|
|
4143
|
+
hub_server: HubServerServiceClient
|
|
4144
|
+
logging: LoggingServiceClient
|
|
4145
|
+
network_instances: NetworkInstancesClient
|
|
4146
|
+
networks: NetworksClient
|
|
4147
|
+
pipelines: PipelinesServiceClient
|
|
4148
|
+
resources: ResourcesServiceClient
|
|
4149
|
+
|
|
4150
|
+
def __init__(self, transport: Transport) -> None:
|
|
4151
|
+
self.blueprints = BlueprintsClient(transport)
|
|
4152
|
+
self.config = ConfigServiceClient(transport)
|
|
4153
|
+
self.hub_client = HubClientServiceClient(transport)
|
|
4154
|
+
self.hub_server = HubServerServiceClient(transport)
|
|
4155
|
+
self.logging = LoggingServiceClient(transport)
|
|
4156
|
+
self.network_instances = NetworkInstancesClient(transport)
|
|
4157
|
+
self.networks = NetworksClient(transport)
|
|
4158
|
+
self.pipelines = PipelinesServiceClient(transport)
|
|
4159
|
+
self.resources = ResourcesServiceClient(transport)
|
|
4160
|
+
|
|
4161
|
+
|
|
4162
|
+
class _AsyncServices:
|
|
4163
|
+
blueprints: AsyncBlueprintsClient
|
|
4164
|
+
config: AsyncConfigServiceClient
|
|
4165
|
+
hub_client: AsyncHubClientServiceClient
|
|
4166
|
+
hub_server: AsyncHubServerServiceClient
|
|
4167
|
+
logging: AsyncLoggingServiceClient
|
|
4168
|
+
network_instances: AsyncNetworkInstancesClient
|
|
4169
|
+
networks: AsyncNetworksClient
|
|
4170
|
+
pipelines: AsyncPipelinesServiceClient
|
|
4171
|
+
resources: AsyncResourcesServiceClient
|
|
4172
|
+
|
|
4173
|
+
def __init__(self, transport: AsyncTransport) -> None:
|
|
4174
|
+
self.blueprints = AsyncBlueprintsClient(transport)
|
|
4175
|
+
self.config = AsyncConfigServiceClient(transport)
|
|
4176
|
+
self.hub_client = AsyncHubClientServiceClient(transport)
|
|
4177
|
+
self.hub_server = AsyncHubServerServiceClient(transport)
|
|
4178
|
+
self.logging = AsyncLoggingServiceClient(transport)
|
|
4179
|
+
self.network_instances = AsyncNetworkInstancesClient(transport)
|
|
4180
|
+
self.networks = AsyncNetworksClient(transport)
|
|
4181
|
+
self.pipelines = AsyncPipelinesServiceClient(transport)
|
|
4182
|
+
self.resources = AsyncResourcesServiceClient(transport)
|