@serve.zone/interfaces 32.11.0 → 32.13.0
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.
- package/changelog.md +29 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/clusternode.d.ts +11 -4
- package/dist_ts/data/clusternode.js +41 -6
- package/dist_ts/data/fleetcutover.d.ts +453 -0
- package/dist_ts/data/fleetcutover.js +943 -0
- package/dist_ts/data/index.d.ts +1 -0
- package/dist_ts/data/index.js +2 -1
- package/dist_ts/data/serviceruntime.d.ts +2 -0
- package/dist_ts/data/serviceruntime.js +3 -1
- package/dist_ts/requests/fleetcutover.d.ts +124 -0
- package/dist_ts/requests/fleetcutover.js +2 -0
- package/dist_ts/requests/index.d.ts +2 -1
- package/dist_ts/requests/index.js +3 -2
- package/dist_ts/requests/service.d.ts +74 -5
- package/package.json +1 -1
- package/readme.md +129 -4
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/clusternode.ts +55 -5
- package/ts/data/fleetcutover.ts +1557 -0
- package/ts/data/index.ts +1 -0
- package/ts/data/serviceruntime.ts +2 -0
- package/ts/requests/fleetcutover.ts +136 -0
- package/ts/requests/index.ts +2 -0
- package/ts/requests/service.ts +83 -5
|
@@ -0,0 +1,943 @@
|
|
|
1
|
+
import { snapshotClusterRuntimeReference } from './clusterruntime.js';
|
|
2
|
+
import { canonicalizeStrictJson, createCanonicalJsonSha256Hex, } from '../private/canonicaljson.js';
|
|
3
|
+
import { captureNetwork, networkCounter, networkDigest, networkId, networkList, networkNodeId, networkRecord, networkReference, networkSorted, requireNetwork, } from '../private/networkcontract.js';
|
|
4
|
+
export const fleetCutoverContract = Object.freeze({
|
|
5
|
+
maximumServices: 512,
|
|
6
|
+
maximumTasks: 4096,
|
|
7
|
+
maximumNodes: 1024,
|
|
8
|
+
maximumContainersPerNode: 512,
|
|
9
|
+
maximumMountsPerOwner: 32,
|
|
10
|
+
maximumClassifications: 512,
|
|
11
|
+
observationFreshnessMs: 300_000,
|
|
12
|
+
mountSourceIdentityDigestDomain: 'serve.zone/fleet-cutover-mount-source-identity',
|
|
13
|
+
mountTargetIdentityDigestDomain: 'serve.zone/fleet-cutover-mount-target-identity',
|
|
14
|
+
mountIdentityDigestDomain: 'serve.zone/fleet-cutover-mount-identity',
|
|
15
|
+
containerSetIdentityDigestDomain: 'serve.zone/fleet-cutover-container-set-identity',
|
|
16
|
+
localNodeSnapshotDigestDomain: 'serve.zone/fleet-cutover-local-node-snapshot',
|
|
17
|
+
managerSnapshotDigestDomain: 'serve.zone/fleet-cutover-manager-snapshot',
|
|
18
|
+
censusDigestDomain: 'serve.zone/fleet-cutover-census',
|
|
19
|
+
scopeDigestDomain: 'serve.zone/fleet-cutover-scope',
|
|
20
|
+
volumeHandoffDigestDomain: 'serve.zone/fleet-cutover-volume-handoff',
|
|
21
|
+
volumeFenceDigestDomain: 'serve.zone/fleet-cutover-volume-fence',
|
|
22
|
+
corestoreAdoptionDigestDomain: 'serve.zone/fleet-cutover-corestore-adoption',
|
|
23
|
+
coreflowRetirementDigestDomain: 'serve.zone/fleet-cutover-coreflow-retirement',
|
|
24
|
+
ingressAuthorityDigestDomain: 'serve.zone/fleet-cutover-ingress-authority',
|
|
25
|
+
legalPhaseTransitions: Object.freeze({
|
|
26
|
+
swarm: 'draining',
|
|
27
|
+
draining: 'switching',
|
|
28
|
+
switching: 'pallet',
|
|
29
|
+
pallet: null,
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
const fail = () => { throw new Error('Fleet cutover contract rejected.'); };
|
|
33
|
+
const safe = (operationArg) => {
|
|
34
|
+
try {
|
|
35
|
+
return operationArg();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return fail();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const nonNegative = (valueArg) => {
|
|
42
|
+
requireNetwork(Number.isSafeInteger(valueArg) && valueArg >= 0);
|
|
43
|
+
return valueArg;
|
|
44
|
+
};
|
|
45
|
+
const literal = (valuesArg, valueArg) => {
|
|
46
|
+
requireNetwork(valuesArg.includes(valueArg));
|
|
47
|
+
return valueArg;
|
|
48
|
+
};
|
|
49
|
+
const sha256Hex = (valueArg) => {
|
|
50
|
+
requireNetwork(typeof valueArg === 'string' && /^[a-f0-9]{64}$/.test(valueArg));
|
|
51
|
+
return valueArg;
|
|
52
|
+
};
|
|
53
|
+
const releaseVersion = (valueArg) => {
|
|
54
|
+
requireNetwork(typeof valueArg === 'string'
|
|
55
|
+
&& /^(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)$/.test(valueArg)
|
|
56
|
+
&& valueArg.length <= 32);
|
|
57
|
+
return valueArg;
|
|
58
|
+
};
|
|
59
|
+
const reference = (valueArg) => networkReference(valueArg);
|
|
60
|
+
const targetSetReference = (valueArg) => {
|
|
61
|
+
const value = networkRecord(valueArg, ['cloudlyClusterId', 'generation', 'targetSetDigest']);
|
|
62
|
+
return {
|
|
63
|
+
cloudlyClusterId: networkId(value.cloudlyClusterId),
|
|
64
|
+
generation: networkCounter(value.generation),
|
|
65
|
+
targetSetDigest: networkDigest(value.targetSetDigest),
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
const runtimeReference = (valueArg) => snapshotClusterRuntimeReference(valueArg);
|
|
69
|
+
const assignmentReference = (valueArg) => {
|
|
70
|
+
const value = networkRecord(valueArg, ['assignmentId', 'generation', 'digest']);
|
|
71
|
+
return {
|
|
72
|
+
assignmentId: networkId(value.assignmentId),
|
|
73
|
+
generation: networkCounter(value.generation),
|
|
74
|
+
digest: networkDigest(value.digest),
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const mountTypeAndClassification = (typeArg, classificationArg) => {
|
|
78
|
+
const type = literal(['volume', 'bind', 'tmpfs', 'unknown'], typeArg);
|
|
79
|
+
const classification = literal([
|
|
80
|
+
'docker-socket', 'cgroup', 'persistent-volume', 'bind', 'tmpfs', 'other', 'unknown',
|
|
81
|
+
], classificationArg);
|
|
82
|
+
requireNetwork((type === 'volume' && ['persistent-volume', 'other', 'unknown'].includes(classification))
|
|
83
|
+
|| (type === 'bind' && ['docker-socket', 'cgroup', 'bind', 'other', 'unknown'].includes(classification))
|
|
84
|
+
|| (type === 'tmpfs' && ['tmpfs', 'other', 'unknown'].includes(classification))
|
|
85
|
+
|| (type === 'unknown' && classification === 'unknown'));
|
|
86
|
+
return { type, classification };
|
|
87
|
+
};
|
|
88
|
+
const mountDescriptor = (valueArg) => {
|
|
89
|
+
const value = networkRecord(valueArg, [
|
|
90
|
+
'type', 'classification', 'sourceIdentityDigest', 'targetIdentityDigest', 'readOnly',
|
|
91
|
+
'mountIdentityDigest',
|
|
92
|
+
]);
|
|
93
|
+
requireNetwork(typeof value.readOnly === 'boolean');
|
|
94
|
+
const shape = mountTypeAndClassification(value.type, value.classification);
|
|
95
|
+
return {
|
|
96
|
+
...shape,
|
|
97
|
+
sourceIdentityDigest: networkDigest(value.sourceIdentityDigest),
|
|
98
|
+
targetIdentityDigest: networkDigest(value.targetIdentityDigest),
|
|
99
|
+
readOnly: value.readOnly,
|
|
100
|
+
mountIdentityDigest: networkDigest(value.mountIdentityDigest),
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const sortedMountDescriptors = (valueArg) => networkSorted(networkList(valueArg, fleetCutoverContract.maximumMountsPerOwner, mountDescriptor), itemArg => itemArg.mountIdentityDigest);
|
|
104
|
+
const dockerMode = (valueArg) => {
|
|
105
|
+
requireNetwork(valueArg !== null && typeof valueArg === 'object');
|
|
106
|
+
const kind = valueArg.kind;
|
|
107
|
+
if (kind === 'global') {
|
|
108
|
+
networkRecord(valueArg, ['kind']);
|
|
109
|
+
return { kind };
|
|
110
|
+
}
|
|
111
|
+
const value = networkRecord(valueArg, ['kind', 'replicas']);
|
|
112
|
+
requireNetwork(kind === 'replicated');
|
|
113
|
+
return { kind, replicas: nonNegative(value.replicas) };
|
|
114
|
+
};
|
|
115
|
+
const ownershipLabels = (valueArg) => {
|
|
116
|
+
const value = networkRecord(valueArg, ['serviceId', 'platformOwner']);
|
|
117
|
+
const serviceId = value.serviceId === null ? null : networkId(value.serviceId);
|
|
118
|
+
const platformOwner = value.platformOwner === null ? null : literal([
|
|
119
|
+
'coreflow', 'corestore', 'coretraffic',
|
|
120
|
+
], value.platformOwner);
|
|
121
|
+
return { serviceId, platformOwner };
|
|
122
|
+
};
|
|
123
|
+
const dockerService = (valueArg) => {
|
|
124
|
+
const value = networkRecord(valueArg, [
|
|
125
|
+
'dockerServiceId', 'dockerServiceName', 'specVersion', 'specDigest', 'imageDigest', 'mode',
|
|
126
|
+
'desiredTaskCount', 'constraintCount', 'constraintSetDigest', 'mounts', 'ownershipLabels',
|
|
127
|
+
]);
|
|
128
|
+
return {
|
|
129
|
+
dockerServiceId: networkId(value.dockerServiceId),
|
|
130
|
+
dockerServiceName: networkId(value.dockerServiceName),
|
|
131
|
+
specVersion: networkCounter(value.specVersion),
|
|
132
|
+
specDigest: networkDigest(value.specDigest),
|
|
133
|
+
imageDigest: networkDigest(value.imageDigest),
|
|
134
|
+
mode: dockerMode(value.mode),
|
|
135
|
+
desiredTaskCount: nonNegative(value.desiredTaskCount),
|
|
136
|
+
constraintCount: nonNegative(value.constraintCount),
|
|
137
|
+
constraintSetDigest: networkDigest(value.constraintSetDigest),
|
|
138
|
+
mounts: sortedMountDescriptors(value.mounts),
|
|
139
|
+
ownershipLabels: ownershipLabels(value.ownershipLabels),
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
const dockerTask = (valueArg) => {
|
|
143
|
+
const value = networkRecord(valueArg, [
|
|
144
|
+
'dockerTaskId', 'dockerServiceId', 'swarmNodeId', 'nodeName', 'desiredState', 'state', 'container',
|
|
145
|
+
]);
|
|
146
|
+
let container = null;
|
|
147
|
+
if (value.container !== null) {
|
|
148
|
+
const containerValue = networkRecord(value.container, ['dockerContainerId']);
|
|
149
|
+
container = {
|
|
150
|
+
dockerContainerId: networkId(containerValue.dockerContainerId),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const swarmNodeId = value.swarmNodeId === null ? null : networkId(value.swarmNodeId);
|
|
154
|
+
const nodeName = value.nodeName === null ? null : networkId(value.nodeName);
|
|
155
|
+
requireNetwork((swarmNodeId === null) === (nodeName === null));
|
|
156
|
+
const taskStates = [
|
|
157
|
+
'new', 'allocated', 'pending', 'assigned', 'accepted', 'preparing', 'ready', 'starting',
|
|
158
|
+
'running', 'complete', 'shutdown', 'failed', 'rejected', 'remove', 'orphaned',
|
|
159
|
+
];
|
|
160
|
+
return {
|
|
161
|
+
dockerTaskId: networkId(value.dockerTaskId),
|
|
162
|
+
dockerServiceId: networkId(value.dockerServiceId),
|
|
163
|
+
swarmNodeId,
|
|
164
|
+
nodeName,
|
|
165
|
+
desiredState: literal(taskStates, value.desiredState),
|
|
166
|
+
state: literal(taskStates, value.state),
|
|
167
|
+
container,
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
const physicalContainer = (valueArg) => {
|
|
171
|
+
const value = networkRecord(valueArg, [
|
|
172
|
+
'dockerContainerId', 'dockerServiceId', 'dockerTaskId', 'imageId', 'serviceIdLabel', 'mounts',
|
|
173
|
+
]);
|
|
174
|
+
return {
|
|
175
|
+
dockerContainerId: networkId(value.dockerContainerId),
|
|
176
|
+
dockerServiceId: value.dockerServiceId === null ? null : networkId(value.dockerServiceId),
|
|
177
|
+
dockerTaskId: value.dockerTaskId === null ? null : networkId(value.dockerTaskId),
|
|
178
|
+
imageId: networkDigest(value.imageId),
|
|
179
|
+
serviceIdLabel: value.serviceIdLabel === null ? null : networkId(value.serviceIdLabel),
|
|
180
|
+
mounts: sortedMountDescriptors(value.mounts),
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
const inventory = (valueArg) => {
|
|
184
|
+
const value = networkRecord(valueArg, [
|
|
185
|
+
'swarmClusterId', 'managerSwarmNodeId', 'services', 'tasks',
|
|
186
|
+
]);
|
|
187
|
+
const services = networkSorted(networkList(value.services, fleetCutoverContract.maximumServices, dockerService), itemArg => itemArg.dockerServiceId);
|
|
188
|
+
const serviceIds = new Set(services.map(itemArg => itemArg.dockerServiceId));
|
|
189
|
+
const tasks = networkSorted(networkList(value.tasks, fleetCutoverContract.maximumTasks, dockerTask), itemArg => `${itemArg.dockerServiceId}\0${itemArg.dockerTaskId}`);
|
|
190
|
+
requireNetwork(tasks.every(itemArg => serviceIds.has(itemArg.dockerServiceId)));
|
|
191
|
+
return {
|
|
192
|
+
swarmClusterId: networkId(value.swarmClusterId),
|
|
193
|
+
managerSwarmNodeId: networkId(value.managerSwarmNodeId),
|
|
194
|
+
services,
|
|
195
|
+
tasks,
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
const observationReference = (valueArg) => {
|
|
199
|
+
const value = networkRecord(valueArg, [
|
|
200
|
+
'observation', 'nodeId', 'swarmNodeId', 'credentialGeneration', 'reporterSessionId',
|
|
201
|
+
'observationSequence', 'observedAt', 'acceptedAt', 'freshUntil', 'observationDigest',
|
|
202
|
+
'snapshotDigest',
|
|
203
|
+
]);
|
|
204
|
+
const result = {
|
|
205
|
+
observation: reference(value.observation),
|
|
206
|
+
nodeId: networkNodeId(value.nodeId),
|
|
207
|
+
swarmNodeId: networkId(value.swarmNodeId),
|
|
208
|
+
credentialGeneration: networkCounter(value.credentialGeneration),
|
|
209
|
+
reporterSessionId: networkId(value.reporterSessionId),
|
|
210
|
+
observationSequence: networkCounter(value.observationSequence),
|
|
211
|
+
observedAt: networkCounter(value.observedAt),
|
|
212
|
+
acceptedAt: networkCounter(value.acceptedAt),
|
|
213
|
+
freshUntil: networkCounter(value.freshUntil),
|
|
214
|
+
observationDigest: networkDigest(value.observationDigest),
|
|
215
|
+
snapshotDigest: networkDigest(value.snapshotDigest),
|
|
216
|
+
};
|
|
217
|
+
requireNetwork(result.acceptedAt >= result.observedAt
|
|
218
|
+
&& result.acceptedAt <= result.freshUntil
|
|
219
|
+
&& result.freshUntil === result.observedAt + fleetCutoverContract.observationFreshnessMs);
|
|
220
|
+
return result;
|
|
221
|
+
};
|
|
222
|
+
const managerCensusRead = (valueArg) => {
|
|
223
|
+
const value = networkRecord(valueArg, [
|
|
224
|
+
'observation', 'nodeId', 'swarmNodeId', 'credentialGeneration', 'reporterSessionId',
|
|
225
|
+
'observationSequence', 'observedAt', 'acceptedAt', 'freshUntil', 'observationDigest',
|
|
226
|
+
'snapshotDigest', 'swarmSnapshotDigest', 'inventoryDigest',
|
|
227
|
+
]);
|
|
228
|
+
return {
|
|
229
|
+
...observationReference({
|
|
230
|
+
observation: value.observation,
|
|
231
|
+
nodeId: value.nodeId,
|
|
232
|
+
swarmNodeId: value.swarmNodeId,
|
|
233
|
+
credentialGeneration: value.credentialGeneration,
|
|
234
|
+
reporterSessionId: value.reporterSessionId,
|
|
235
|
+
observationSequence: value.observationSequence,
|
|
236
|
+
observedAt: value.observedAt,
|
|
237
|
+
acceptedAt: value.acceptedAt,
|
|
238
|
+
freshUntil: value.freshUntil,
|
|
239
|
+
observationDigest: value.observationDigest,
|
|
240
|
+
snapshotDigest: value.snapshotDigest,
|
|
241
|
+
}),
|
|
242
|
+
swarmSnapshotDigest: networkDigest(value.swarmSnapshotDigest),
|
|
243
|
+
inventoryDigest: networkDigest(value.inventoryDigest),
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
const canonicalDigest = async (domainArg, valueArg) => {
|
|
247
|
+
const { digest: _digest, ...payload } = valueArg;
|
|
248
|
+
return `sha256:${await createCanonicalJsonSha256Hex(canonicalizeStrictJson({
|
|
249
|
+
domain: domainArg,
|
|
250
|
+
payload,
|
|
251
|
+
}, fail), fail)}`;
|
|
252
|
+
};
|
|
253
|
+
const exactDockerText = (valueArg, allowEmptyArg) => {
|
|
254
|
+
requireNetwork(typeof valueArg === 'string'
|
|
255
|
+
&& new TextEncoder().encode(valueArg).length <= 4096
|
|
256
|
+
&& (allowEmptyArg || valueArg.length > 0));
|
|
257
|
+
return valueArg;
|
|
258
|
+
};
|
|
259
|
+
const computeExactIdentityDigest = async (domainArg, inputArg) => `sha256:${await createCanonicalJsonSha256Hex(canonicalizeStrictJson({
|
|
260
|
+
domain: domainArg,
|
|
261
|
+
input: inputArg,
|
|
262
|
+
}, fail), fail)}`;
|
|
263
|
+
export const computeFleetCutoverMountSourceIdentityDigest = async (valueArg) => safe(async () => {
|
|
264
|
+
const value = networkRecord(valueArg, ['type', 'source']);
|
|
265
|
+
return computeExactIdentityDigest(fleetCutoverContract.mountSourceIdentityDigestDomain, {
|
|
266
|
+
type: literal(['volume', 'bind', 'tmpfs', 'unknown'], value.type),
|
|
267
|
+
source: exactDockerText(value.source, true),
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
export const computeFleetCutoverMountTargetIdentityDigest = async (valueArg) => safe(async () => {
|
|
271
|
+
const value = networkRecord(valueArg, ['target']);
|
|
272
|
+
return computeExactIdentityDigest(fleetCutoverContract.mountTargetIdentityDigestDomain, {
|
|
273
|
+
target: exactDockerText(value.target, false),
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
export const computeFleetCutoverMountIdentityDigest = async (valueArg) => safe(async () => {
|
|
277
|
+
const value = networkRecord(valueArg, [
|
|
278
|
+
'type', 'classification', 'sourceIdentityDigest', 'targetIdentityDigest', 'readOnly',
|
|
279
|
+
]);
|
|
280
|
+
requireNetwork(typeof value.readOnly === 'boolean');
|
|
281
|
+
const shape = mountTypeAndClassification(value.type, value.classification);
|
|
282
|
+
return computeExactIdentityDigest(fleetCutoverContract.mountIdentityDigestDomain, {
|
|
283
|
+
...shape,
|
|
284
|
+
sourceIdentityDigest: networkDigest(value.sourceIdentityDigest),
|
|
285
|
+
targetIdentityDigest: networkDigest(value.targetIdentityDigest),
|
|
286
|
+
readOnly: value.readOnly,
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
const validateMountDescriptors = async (mountsArg) => {
|
|
290
|
+
for (const mount of mountsArg) {
|
|
291
|
+
const { mountIdentityDigest, ...input } = mount;
|
|
292
|
+
requireNetwork(mountIdentityDigest === await computeFleetCutoverMountIdentityDigest(input));
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
export const computeFleetCutoverContainerSetIdentityDigest = async (containerIdsArg) => safe(async () => {
|
|
296
|
+
const containerIds = networkSorted(networkList(containerIdsArg, fleetCutoverContract.maximumContainersPerNode, networkId), itemArg => itemArg);
|
|
297
|
+
return computeExactIdentityDigest(fleetCutoverContract.containerSetIdentityDigestDomain, {
|
|
298
|
+
containerIds,
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
const containerSetIdentity = (valueArg) => {
|
|
302
|
+
const value = networkRecord(valueArg, ['containerCount', 'containerIdsDigest']);
|
|
303
|
+
return {
|
|
304
|
+
containerCount: nonNegative(value.containerCount),
|
|
305
|
+
containerIdsDigest: networkDigest(value.containerIdsDigest),
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
export const snapshotFleetCutoverLocalNodeSnapshot = (valueArg) => safe(() => {
|
|
309
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
310
|
+
'swarmNodeId', 'before', 'containers', 'after', 'snapshotDigest',
|
|
311
|
+
]);
|
|
312
|
+
const containers = networkSorted(networkList(value.containers, fleetCutoverContract.maximumContainersPerNode, physicalContainer), itemArg => itemArg.dockerContainerId);
|
|
313
|
+
const before = containerSetIdentity(value.before);
|
|
314
|
+
const after = containerSetIdentity(value.after);
|
|
315
|
+
requireNetwork(before.containerCount === containers.length
|
|
316
|
+
&& after.containerCount === containers.length
|
|
317
|
+
&& before.containerIdsDigest === after.containerIdsDigest);
|
|
318
|
+
return {
|
|
319
|
+
swarmNodeId: networkId(value.swarmNodeId),
|
|
320
|
+
before,
|
|
321
|
+
containers,
|
|
322
|
+
after,
|
|
323
|
+
snapshotDigest: networkDigest(value.snapshotDigest),
|
|
324
|
+
};
|
|
325
|
+
});
|
|
326
|
+
export const computeFleetCutoverLocalNodeSnapshotDigest = async (valueArg) => safe(async () => {
|
|
327
|
+
const value = snapshotFleetCutoverLocalNodeSnapshot(valueArg);
|
|
328
|
+
const { snapshotDigest: _omitted, ...input } = value;
|
|
329
|
+
return computeExactIdentityDigest(fleetCutoverContract.localNodeSnapshotDigestDomain, input);
|
|
330
|
+
});
|
|
331
|
+
export const validateFleetCutoverLocalNodeSnapshot = async (valueArg) => {
|
|
332
|
+
try {
|
|
333
|
+
const value = snapshotFleetCutoverLocalNodeSnapshot(valueArg);
|
|
334
|
+
const containerIdsDigest = await computeFleetCutoverContainerSetIdentityDigest(value.containers.map(itemArg => itemArg.dockerContainerId));
|
|
335
|
+
requireNetwork(value.before.containerIdsDigest === containerIdsDigest
|
|
336
|
+
&& value.after.containerIdsDigest === containerIdsDigest);
|
|
337
|
+
for (const container of value.containers)
|
|
338
|
+
await validateMountDescriptors(container.mounts);
|
|
339
|
+
return value.snapshotDigest === await computeFleetCutoverLocalNodeSnapshotDigest(value)
|
|
340
|
+
? [] : ['fleet cutover local node snapshot digest does not match'];
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return ['fleet cutover local node snapshot must use its exact canonical schema'];
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
export const computeFleetCutoverInventoryDigest = async (valueArg) => safe(async () => {
|
|
347
|
+
const hex = await createCanonicalJsonSha256Hex(canonicalizeStrictJson({
|
|
348
|
+
domain: 'serve.zone/fleet-cutover-inventory',
|
|
349
|
+
inventory: inventory(captureNetwork(valueArg)),
|
|
350
|
+
}, fail), fail);
|
|
351
|
+
return `sha256:${hex}`;
|
|
352
|
+
});
|
|
353
|
+
export const snapshotFleetCutoverManagerSnapshot = async (valueArg) => safe(async () => {
|
|
354
|
+
const value = networkRecord(captureNetwork(valueArg), ['inventory', 'inventoryDigest']);
|
|
355
|
+
const inventoryValue = inventory(value.inventory);
|
|
356
|
+
const inventoryDigest = networkDigest(value.inventoryDigest);
|
|
357
|
+
requireNetwork(inventoryDigest === await computeFleetCutoverInventoryDigest(inventoryValue));
|
|
358
|
+
for (const service of inventoryValue.services)
|
|
359
|
+
await validateMountDescriptors(service.mounts);
|
|
360
|
+
return { inventory: inventoryValue, inventoryDigest };
|
|
361
|
+
});
|
|
362
|
+
export const computeFleetCutoverManagerSnapshotDigest = async (valueArg) => computeExactIdentityDigest(fleetCutoverContract.managerSnapshotDigestDomain, await snapshotFleetCutoverManagerSnapshot(valueArg));
|
|
363
|
+
export const validateFleetCutoverManagerSnapshot = async (valueArg) => {
|
|
364
|
+
try {
|
|
365
|
+
await snapshotFleetCutoverManagerSnapshot(valueArg);
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return ['fleet cutover manager snapshot must use its exact canonical schema'];
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
export const snapshotFleetCutoverCensusCandidate = async (valueArg) => safe(async () => {
|
|
373
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
374
|
+
'clusterId', 'runtime', 'targetSet', 'inventory', 'managerReads', 'nodeObservations',
|
|
375
|
+
'freshUntil',
|
|
376
|
+
]);
|
|
377
|
+
const clusterId = networkId(value.clusterId);
|
|
378
|
+
const runtime = runtimeReference(value.runtime);
|
|
379
|
+
const targetSet = targetSetReference(value.targetSet);
|
|
380
|
+
const inventoryValue = inventory(value.inventory);
|
|
381
|
+
for (const service of inventoryValue.services)
|
|
382
|
+
await validateMountDescriptors(service.mounts);
|
|
383
|
+
const managerReads = networkList(value.managerReads, 2, managerCensusRead);
|
|
384
|
+
const nodeObservations = networkSorted(networkList(value.nodeObservations, fleetCutoverContract.maximumNodes, observationReference), itemArg => `${itemArg.nodeId}\0${itemArg.swarmNodeId}`);
|
|
385
|
+
requireNetwork(managerReads.length === 2
|
|
386
|
+
&& managerReads[1].nodeId === managerReads[0].nodeId
|
|
387
|
+
&& managerReads[1].swarmNodeId === managerReads[0].swarmNodeId
|
|
388
|
+
&& managerReads[1].credentialGeneration === managerReads[0].credentialGeneration
|
|
389
|
+
&& managerReads[1].reporterSessionId === managerReads[0].reporterSessionId
|
|
390
|
+
&& managerReads[1].observationSequence === managerReads[0].observationSequence + 1
|
|
391
|
+
&& managerReads[1].observedAt > managerReads[0].observedAt
|
|
392
|
+
&& managerReads[1].swarmSnapshotDigest === managerReads[0].swarmSnapshotDigest
|
|
393
|
+
&& managerReads.every(itemArg => itemArg.swarmNodeId === inventoryValue.managerSwarmNodeId)
|
|
394
|
+
&& nodeObservations.length > 0
|
|
395
|
+
&& new Set(nodeObservations.map(itemArg => itemArg.nodeId)).size === nodeObservations.length
|
|
396
|
+
&& new Set(nodeObservations.map(itemArg => itemArg.swarmNodeId)).size === nodeObservations.length
|
|
397
|
+
&& runtime.id === clusterId
|
|
398
|
+
&& targetSet.cloudlyClusterId === clusterId);
|
|
399
|
+
const inventoryDigest = await computeFleetCutoverInventoryDigest(inventoryValue);
|
|
400
|
+
const managerSnapshotDigest = await computeFleetCutoverManagerSnapshotDigest({
|
|
401
|
+
inventory: inventoryValue,
|
|
402
|
+
inventoryDigest,
|
|
403
|
+
});
|
|
404
|
+
requireNetwork(managerReads.every(itemArg => itemArg.inventoryDigest === inventoryDigest
|
|
405
|
+
&& itemArg.snapshotDigest === managerSnapshotDigest));
|
|
406
|
+
const freshUntil = networkCounter(value.freshUntil);
|
|
407
|
+
requireNetwork(freshUntil === Math.min(...managerReads.map(itemArg => itemArg.freshUntil), ...nodeObservations.map(itemArg => itemArg.freshUntil)));
|
|
408
|
+
return {
|
|
409
|
+
clusterId,
|
|
410
|
+
runtime,
|
|
411
|
+
targetSet,
|
|
412
|
+
inventory: inventoryValue,
|
|
413
|
+
managerReads: managerReads,
|
|
414
|
+
nodeObservations,
|
|
415
|
+
freshUntil,
|
|
416
|
+
};
|
|
417
|
+
});
|
|
418
|
+
export const snapshotFleetCutoverCensus = async (valueArg) => safe(async () => {
|
|
419
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
420
|
+
'id', 'generation', 'acceptedAt', 'digest', 'clusterId', 'runtime', 'targetSet',
|
|
421
|
+
'inventory', 'managerReads', 'nodeObservations', 'freshUntil',
|
|
422
|
+
]);
|
|
423
|
+
const candidate = await snapshotFleetCutoverCensusCandidate({
|
|
424
|
+
clusterId: value.clusterId,
|
|
425
|
+
runtime: value.runtime,
|
|
426
|
+
targetSet: value.targetSet,
|
|
427
|
+
inventory: value.inventory,
|
|
428
|
+
managerReads: value.managerReads,
|
|
429
|
+
nodeObservations: value.nodeObservations,
|
|
430
|
+
freshUntil: value.freshUntil,
|
|
431
|
+
});
|
|
432
|
+
const acceptedAt = networkCounter(value.acceptedAt);
|
|
433
|
+
requireNetwork(acceptedAt <= candidate.freshUntil
|
|
434
|
+
&& candidate.managerReads.every(itemArg => acceptedAt >= itemArg.acceptedAt)
|
|
435
|
+
&& candidate.nodeObservations.every(itemArg => acceptedAt >= itemArg.acceptedAt));
|
|
436
|
+
return {
|
|
437
|
+
id: networkId(value.id),
|
|
438
|
+
generation: networkCounter(value.generation),
|
|
439
|
+
acceptedAt,
|
|
440
|
+
digest: networkDigest(value.digest),
|
|
441
|
+
...candidate,
|
|
442
|
+
};
|
|
443
|
+
});
|
|
444
|
+
export const computeFleetCutoverCensusDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.censusDigestDomain, await snapshotFleetCutoverCensus(valueArg));
|
|
445
|
+
export const validateFleetCutoverCensus = async (valueArg) => {
|
|
446
|
+
try {
|
|
447
|
+
const value = await snapshotFleetCutoverCensus(valueArg);
|
|
448
|
+
return value.digest === await computeFleetCutoverCensusDigest(value)
|
|
449
|
+
? [] : ['fleet cutover census digest does not match'];
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
return ['fleet cutover census must use its exact canonical schema'];
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
export const fleetCutoverEvidenceReferenceOf = (valueArg) => reference({
|
|
456
|
+
id: valueArg.id,
|
|
457
|
+
generation: valueArg.generation,
|
|
458
|
+
digest: valueArg.digest,
|
|
459
|
+
});
|
|
460
|
+
export const snapshotFleetCutoverAcceptedEvidenceReference = (valueArg) => safe(() => reference(captureNetwork(valueArg)));
|
|
461
|
+
const scopeEntry = (valueArg) => {
|
|
462
|
+
const value = networkRecord(valueArg, [
|
|
463
|
+
'dockerServiceId', 'serviceId', 'owner', 'serviceAuthority', 'classificationAuthority',
|
|
464
|
+
]);
|
|
465
|
+
const owner = literal([
|
|
466
|
+
'application', 'coreflow', 'corestore', 'coretraffic', 'unknown',
|
|
467
|
+
], value.owner);
|
|
468
|
+
const serviceId = value.serviceId === null ? null : networkId(value.serviceId);
|
|
469
|
+
const serviceAuthority = value.serviceAuthority === null ? null : reference(value.serviceAuthority);
|
|
470
|
+
const classificationAuthority = value.classificationAuthority === null
|
|
471
|
+
? null : reference(value.classificationAuthority);
|
|
472
|
+
requireNetwork(owner === 'unknown'
|
|
473
|
+
? serviceId === null && serviceAuthority === null && classificationAuthority === null
|
|
474
|
+
: serviceId !== null && serviceAuthority !== null && classificationAuthority !== null);
|
|
475
|
+
return {
|
|
476
|
+
dockerServiceId: networkId(value.dockerServiceId),
|
|
477
|
+
serviceId,
|
|
478
|
+
owner,
|
|
479
|
+
serviceAuthority,
|
|
480
|
+
classificationAuthority,
|
|
481
|
+
};
|
|
482
|
+
};
|
|
483
|
+
export const snapshotFleetCutoverScope = (valueArg) => safe(() => {
|
|
484
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
485
|
+
'id', 'generation', 'previous', 'state', 'clusterId', 'census', 'runtime', 'targetSet', 'entries',
|
|
486
|
+
'actorId', 'acceptedAt', 'digest',
|
|
487
|
+
]);
|
|
488
|
+
const state = literal(['incomplete', 'complete'], value.state);
|
|
489
|
+
const id = networkId(value.id);
|
|
490
|
+
const generation = networkCounter(value.generation);
|
|
491
|
+
const previous = value.previous === null ? null : reference(value.previous);
|
|
492
|
+
const clusterId = networkId(value.clusterId);
|
|
493
|
+
const runtime = runtimeReference(value.runtime);
|
|
494
|
+
const targetSet = targetSetReference(value.targetSet);
|
|
495
|
+
const entries = networkSorted(networkList(value.entries, fleetCutoverContract.maximumServices, scopeEntry), itemArg => itemArg.dockerServiceId);
|
|
496
|
+
requireNetwork(runtime.id === clusterId
|
|
497
|
+
&& targetSet.cloudlyClusterId === clusterId
|
|
498
|
+
&& (generation === 1
|
|
499
|
+
? previous === null && state === 'incomplete'
|
|
500
|
+
: previous?.id === id && previous.generation === generation - 1)
|
|
501
|
+
&& (state === 'incomplete' || entries.every(itemArg => itemArg.owner !== 'unknown')));
|
|
502
|
+
return {
|
|
503
|
+
id,
|
|
504
|
+
generation,
|
|
505
|
+
previous,
|
|
506
|
+
state,
|
|
507
|
+
clusterId,
|
|
508
|
+
census: reference(value.census),
|
|
509
|
+
runtime,
|
|
510
|
+
targetSet,
|
|
511
|
+
entries,
|
|
512
|
+
actorId: networkId(value.actorId),
|
|
513
|
+
acceptedAt: networkCounter(value.acceptedAt),
|
|
514
|
+
digest: networkDigest(value.digest),
|
|
515
|
+
};
|
|
516
|
+
});
|
|
517
|
+
export const computeFleetCutoverScopeDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.scopeDigestDomain, snapshotFleetCutoverScope(valueArg));
|
|
518
|
+
export const validateFleetCutoverScope = async (valueArg) => {
|
|
519
|
+
try {
|
|
520
|
+
const value = snapshotFleetCutoverScope(valueArg);
|
|
521
|
+
return value.digest === await computeFleetCutoverScopeDigest(value)
|
|
522
|
+
? [] : ['fleet cutover scope digest does not match'];
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
return ['fleet cutover scope must use its exact canonical schema'];
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
export const snapshotFleetCutoverScopeClassificationRequest = (valueArg) => safe(() => {
|
|
529
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
530
|
+
'mutationId', 'clusterId', 'expectedScopeGeneration', 'census', 'classifications',
|
|
531
|
+
]);
|
|
532
|
+
const classifications = networkSorted(networkList(value.classifications, fleetCutoverContract.maximumClassifications, itemArg => {
|
|
533
|
+
const item = networkRecord(itemArg, ['dockerServiceId', 'serviceId', 'owner']);
|
|
534
|
+
return {
|
|
535
|
+
dockerServiceId: networkId(item.dockerServiceId),
|
|
536
|
+
serviceId: networkId(item.serviceId),
|
|
537
|
+
owner: literal(['application', 'coreflow', 'corestore', 'coretraffic'], item.owner),
|
|
538
|
+
};
|
|
539
|
+
}), itemArg => itemArg.dockerServiceId);
|
|
540
|
+
return {
|
|
541
|
+
mutationId: networkId(value.mutationId),
|
|
542
|
+
clusterId: networkId(value.clusterId),
|
|
543
|
+
expectedScopeGeneration: networkCounter(value.expectedScopeGeneration),
|
|
544
|
+
census: reference(value.census),
|
|
545
|
+
classifications,
|
|
546
|
+
};
|
|
547
|
+
});
|
|
548
|
+
export const snapshotFleetCutoverTargetSetReference = (valueArg) => safe(() => targetSetReference(captureNetwork(valueArg)));
|
|
549
|
+
const volumeHandoff = (valueArg) => {
|
|
550
|
+
const value = networkRecord(valueArg, [
|
|
551
|
+
'id', 'generation', 'clusterId', 'nodeId', 'serviceId', 'volumeId',
|
|
552
|
+
'mountIdentityDigest', 'sourceLineageDigest', 'storageRequestDigest', 'runtime', 'scope',
|
|
553
|
+
'targetSet', 'legacyStorageEvidence', 'sourceNodeObservation', 'acceptedAt', 'digest',
|
|
554
|
+
]);
|
|
555
|
+
const clusterId = networkId(value.clusterId);
|
|
556
|
+
const runtime = runtimeReference(value.runtime);
|
|
557
|
+
const targetSet = targetSetReference(value.targetSet);
|
|
558
|
+
requireNetwork(runtime.id === clusterId && runtime.phase === 'draining'
|
|
559
|
+
&& targetSet.cloudlyClusterId === clusterId);
|
|
560
|
+
return {
|
|
561
|
+
id: networkId(value.id),
|
|
562
|
+
generation: networkCounter(value.generation),
|
|
563
|
+
clusterId,
|
|
564
|
+
nodeId: networkNodeId(value.nodeId),
|
|
565
|
+
serviceId: networkId(value.serviceId),
|
|
566
|
+
volumeId: networkId(value.volumeId),
|
|
567
|
+
mountIdentityDigest: networkDigest(value.mountIdentityDigest),
|
|
568
|
+
sourceLineageDigest: networkDigest(value.sourceLineageDigest),
|
|
569
|
+
storageRequestDigest: networkDigest(value.storageRequestDigest),
|
|
570
|
+
runtime: runtime,
|
|
571
|
+
scope: reference(value.scope),
|
|
572
|
+
targetSet,
|
|
573
|
+
legacyStorageEvidence: reference(value.legacyStorageEvidence),
|
|
574
|
+
sourceNodeObservation: reference(value.sourceNodeObservation),
|
|
575
|
+
acceptedAt: networkCounter(value.acceptedAt),
|
|
576
|
+
digest: networkDigest(value.digest),
|
|
577
|
+
};
|
|
578
|
+
};
|
|
579
|
+
export const snapshotFleetCutoverVolumeHandoffIntent = (valueArg) => safe(() => volumeHandoff(captureNetwork(valueArg)));
|
|
580
|
+
export const computeFleetCutoverVolumeHandoffDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.volumeHandoffDigestDomain, snapshotFleetCutoverVolumeHandoffIntent(valueArg));
|
|
581
|
+
const volumeFence = (valueArg) => {
|
|
582
|
+
requireNetwork(valueArg !== null && typeof valueArg === 'object');
|
|
583
|
+
const state = valueArg.state;
|
|
584
|
+
const consumedKeys = state === 'consumed'
|
|
585
|
+
? ['consumedRuntime', 'adoptionReceipt', 'claim', 'consumedAt'] : [];
|
|
586
|
+
const value = networkRecord(valueArg, [
|
|
587
|
+
'id', 'generation', 'previous', 'clusterId', 'nodeId', 'serviceId', 'volumeId',
|
|
588
|
+
'mountIdentityDigest', 'handoffIntent', 'heldRuntime', 'heldAt', 'state', ...consumedKeys,
|
|
589
|
+
'digest',
|
|
590
|
+
]);
|
|
591
|
+
requireNetwork(state === 'held' || state === 'consumed');
|
|
592
|
+
const id = networkId(value.id);
|
|
593
|
+
const generation = networkCounter(value.generation);
|
|
594
|
+
const previous = value.previous === null ? null : reference(value.previous);
|
|
595
|
+
requireNetwork(generation === 1
|
|
596
|
+
? previous === null
|
|
597
|
+
: previous?.id === id && previous.generation === generation - 1);
|
|
598
|
+
const heldRuntime = runtimeReference(value.heldRuntime);
|
|
599
|
+
requireNetwork(heldRuntime.phase === 'draining');
|
|
600
|
+
const base = {
|
|
601
|
+
id,
|
|
602
|
+
generation,
|
|
603
|
+
previous,
|
|
604
|
+
clusterId: networkId(value.clusterId),
|
|
605
|
+
nodeId: networkNodeId(value.nodeId),
|
|
606
|
+
serviceId: networkId(value.serviceId),
|
|
607
|
+
volumeId: networkId(value.volumeId),
|
|
608
|
+
mountIdentityDigest: networkDigest(value.mountIdentityDigest),
|
|
609
|
+
handoffIntent: reference(value.handoffIntent),
|
|
610
|
+
heldRuntime: heldRuntime,
|
|
611
|
+
heldAt: networkCounter(value.heldAt),
|
|
612
|
+
digest: networkDigest(value.digest),
|
|
613
|
+
};
|
|
614
|
+
if (state === 'held')
|
|
615
|
+
return { ...base, state };
|
|
616
|
+
const consumedRuntime = runtimeReference(value.consumedRuntime);
|
|
617
|
+
requireNetwork(consumedRuntime.phase === 'pallet');
|
|
618
|
+
return {
|
|
619
|
+
...base,
|
|
620
|
+
state,
|
|
621
|
+
consumedRuntime: consumedRuntime,
|
|
622
|
+
adoptionReceipt: reference(value.adoptionReceipt),
|
|
623
|
+
claim: reference(value.claim),
|
|
624
|
+
consumedAt: networkCounter(value.consumedAt),
|
|
625
|
+
};
|
|
626
|
+
};
|
|
627
|
+
export const snapshotFleetCutoverVolumeFence = (valueArg) => safe(() => volumeFence(captureNetwork(valueArg)));
|
|
628
|
+
export const computeFleetCutoverVolumeFenceDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.volumeFenceDigestDomain, snapshotFleetCutoverVolumeFence(valueArg));
|
|
629
|
+
const corestoreAdoption = (valueArg) => {
|
|
630
|
+
const value = networkRecord(valueArg, [
|
|
631
|
+
'id', 'generation', 'clusterId', 'nodeId', 'serviceId', 'volumeId',
|
|
632
|
+
'mountIdentityDigest', 'handoffIntent', 'palletFence', 'sourceLineageDigest', 'claim',
|
|
633
|
+
'accessMode', 'acceptedAt', 'digest',
|
|
634
|
+
]);
|
|
635
|
+
requireNetwork(value.generation === 1 && value.accessMode === 'ReadWriteOnce');
|
|
636
|
+
return {
|
|
637
|
+
id: networkId(value.id),
|
|
638
|
+
generation: 1,
|
|
639
|
+
clusterId: networkId(value.clusterId),
|
|
640
|
+
nodeId: networkNodeId(value.nodeId),
|
|
641
|
+
serviceId: networkId(value.serviceId),
|
|
642
|
+
volumeId: networkId(value.volumeId),
|
|
643
|
+
mountIdentityDigest: networkDigest(value.mountIdentityDigest),
|
|
644
|
+
handoffIntent: reference(value.handoffIntent),
|
|
645
|
+
palletFence: reference(value.palletFence),
|
|
646
|
+
sourceLineageDigest: networkDigest(value.sourceLineageDigest),
|
|
647
|
+
claim: reference(value.claim),
|
|
648
|
+
accessMode: 'ReadWriteOnce',
|
|
649
|
+
acceptedAt: networkCounter(value.acceptedAt),
|
|
650
|
+
digest: networkDigest(value.digest),
|
|
651
|
+
};
|
|
652
|
+
};
|
|
653
|
+
export const snapshotFleetCutoverCorestoreAdoptionReceipt = (valueArg) => safe(() => corestoreAdoption(captureNetwork(valueArg)));
|
|
654
|
+
export const computeFleetCutoverCorestoreAdoptionDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.corestoreAdoptionDigestDomain, snapshotFleetCutoverCorestoreAdoptionReceipt(valueArg));
|
|
655
|
+
/** Content join only. The Pallet owner must dereference both accepted records while holding its CAS. */
|
|
656
|
+
export const bindFleetCutoverAdoptionToVolumeFence = (adoptionArg, fenceArg) => safe(() => {
|
|
657
|
+
const adoption = snapshotFleetCutoverCorestoreAdoptionReceipt(adoptionArg);
|
|
658
|
+
const fence = snapshotFleetCutoverVolumeFence(fenceArg);
|
|
659
|
+
requireNetwork(fence.state === 'held'
|
|
660
|
+
&& adoption.clusterId === fence.clusterId
|
|
661
|
+
&& adoption.nodeId === fence.nodeId
|
|
662
|
+
&& adoption.serviceId === fence.serviceId
|
|
663
|
+
&& adoption.volumeId === fence.volumeId
|
|
664
|
+
&& adoption.mountIdentityDigest === fence.mountIdentityDigest
|
|
665
|
+
&& adoption.handoffIntent.id === fence.handoffIntent.id
|
|
666
|
+
&& adoption.handoffIntent.generation === fence.handoffIntent.generation
|
|
667
|
+
&& adoption.handoffIntent.digest === fence.handoffIntent.digest
|
|
668
|
+
&& adoption.palletFence.id === fence.id
|
|
669
|
+
&& adoption.palletFence.generation === fence.generation
|
|
670
|
+
&& adoption.palletFence.digest === fence.digest);
|
|
671
|
+
return { adoption, fence };
|
|
672
|
+
});
|
|
673
|
+
export const validateFleetCutoverVolumeHandoffIntent = async (valueArg) => {
|
|
674
|
+
try {
|
|
675
|
+
const value = snapshotFleetCutoverVolumeHandoffIntent(valueArg);
|
|
676
|
+
return value.digest === await computeFleetCutoverVolumeHandoffDigest(value)
|
|
677
|
+
? [] : ['fleet cutover volume handoff digest does not match'];
|
|
678
|
+
}
|
|
679
|
+
catch {
|
|
680
|
+
return ['fleet cutover volume handoff must use its exact canonical schema'];
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
export const validateFleetCutoverVolumeFence = async (valueArg) => {
|
|
684
|
+
try {
|
|
685
|
+
const value = snapshotFleetCutoverVolumeFence(valueArg);
|
|
686
|
+
return value.digest === await computeFleetCutoverVolumeFenceDigest(value)
|
|
687
|
+
? [] : ['fleet cutover volume fence digest does not match'];
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
return ['fleet cutover volume fence must use its exact canonical schema'];
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
export const validateFleetCutoverCorestoreAdoptionReceipt = async (valueArg) => {
|
|
694
|
+
try {
|
|
695
|
+
const value = snapshotFleetCutoverCorestoreAdoptionReceipt(valueArg);
|
|
696
|
+
return value.digest === await computeFleetCutoverCorestoreAdoptionDigest(value)
|
|
697
|
+
? [] : ['fleet cutover Corestore adoption digest does not match'];
|
|
698
|
+
}
|
|
699
|
+
catch {
|
|
700
|
+
return ['fleet cutover Corestore adoption receipt must use its exact canonical schema'];
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
const runtimeSession = (valueArg) => {
|
|
704
|
+
const value = networkRecord(valueArg, [
|
|
705
|
+
'reporterSessionId', 'nodeId', 'clusterId', 'credentialGeneration', 'sessionEpoch',
|
|
706
|
+
'controllerInstanceId', 'controller', 'runtimeNamespace',
|
|
707
|
+
]);
|
|
708
|
+
const controller = networkRecord(value.controller, ['kind', 'id', 'epoch']);
|
|
709
|
+
requireNetwork(controller.kind === 'cloudly' || controller.kind === 'onebox');
|
|
710
|
+
return {
|
|
711
|
+
reporterSessionId: networkId(value.reporterSessionId),
|
|
712
|
+
nodeId: networkNodeId(value.nodeId),
|
|
713
|
+
clusterId: networkId(value.clusterId),
|
|
714
|
+
credentialGeneration: networkCounter(value.credentialGeneration),
|
|
715
|
+
sessionEpoch: networkCounter(value.sessionEpoch),
|
|
716
|
+
controllerInstanceId: networkId(value.controllerInstanceId),
|
|
717
|
+
controller: {
|
|
718
|
+
kind: controller.kind,
|
|
719
|
+
id: networkId(controller.id),
|
|
720
|
+
epoch: networkId(controller.epoch),
|
|
721
|
+
},
|
|
722
|
+
runtimeNamespace: networkId(value.runtimeNamespace),
|
|
723
|
+
};
|
|
724
|
+
};
|
|
725
|
+
export const snapshotFleetCutoverCoreflowRetirementEvidence = (valueArg) => safe(() => {
|
|
726
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
727
|
+
'id', 'generation', 'clusterId', 'scope', 'targetSet', 'runtime', 'relay', 'spark',
|
|
728
|
+
'legacy', 'acceptedAt', 'digest',
|
|
729
|
+
]);
|
|
730
|
+
const relay = networkRecord(value.relay, [
|
|
731
|
+
'serviceId', 'nodeId', 'dockerServiceId', 'dockerContainerId', 'specVersion', 'specDigest',
|
|
732
|
+
'imageDigest', 'managerObservation', 'nodeObservation', 'credential',
|
|
733
|
+
'acceptedRegistration', 'version',
|
|
734
|
+
]);
|
|
735
|
+
const spark = networkRecord(value.spark, [
|
|
736
|
+
'nodeId', 'credentialGeneration', 'reporterSessionId', 'observationSequence',
|
|
737
|
+
'observation', 'bundleVersion', 'bundleSourceCommit',
|
|
738
|
+
'bundleManifestSha256', 'unitName', 'unitDigest',
|
|
739
|
+
]);
|
|
740
|
+
const legacy = networkRecord(value.legacy, [
|
|
741
|
+
'credential', 'invalidation', 'oldModeRefusal', 'configurationCas',
|
|
742
|
+
'sourceOwnerGeneration', 'sourceSha256', 'sourceDisposition',
|
|
743
|
+
]);
|
|
744
|
+
const clusterId = networkId(value.clusterId);
|
|
745
|
+
const runtime = runtimeReference(value.runtime);
|
|
746
|
+
const targetSet = targetSetReference(value.targetSet);
|
|
747
|
+
requireNetwork(runtime.id === clusterId && runtime.phase === 'swarm'
|
|
748
|
+
&& targetSet.cloudlyClusterId === clusterId);
|
|
749
|
+
const relayNodeId = networkNodeId(relay.nodeId);
|
|
750
|
+
const sparkNodeId = networkNodeId(spark.nodeId);
|
|
751
|
+
requireNetwork(relayNodeId === sparkNodeId);
|
|
752
|
+
const relayNodeObservation = reference(relay.nodeObservation);
|
|
753
|
+
const sparkObservation = reference(spark.observation);
|
|
754
|
+
requireNetwork(relayNodeObservation.id === sparkObservation.id
|
|
755
|
+
&& relayNodeObservation.generation === sparkObservation.generation
|
|
756
|
+
&& relayNodeObservation.digest === sparkObservation.digest);
|
|
757
|
+
const relayVersion = releaseVersion(relay.version);
|
|
758
|
+
requireNetwork(relayVersion.startsWith('32.'));
|
|
759
|
+
return {
|
|
760
|
+
id: networkId(value.id),
|
|
761
|
+
generation: networkCounter(value.generation),
|
|
762
|
+
clusterId,
|
|
763
|
+
scope: reference(value.scope),
|
|
764
|
+
targetSet,
|
|
765
|
+
runtime,
|
|
766
|
+
relay: {
|
|
767
|
+
serviceId: networkId(relay.serviceId),
|
|
768
|
+
nodeId: relayNodeId,
|
|
769
|
+
dockerServiceId: networkId(relay.dockerServiceId),
|
|
770
|
+
dockerContainerId: networkId(relay.dockerContainerId),
|
|
771
|
+
specVersion: networkCounter(relay.specVersion),
|
|
772
|
+
specDigest: networkDigest(relay.specDigest),
|
|
773
|
+
imageDigest: networkDigest(relay.imageDigest),
|
|
774
|
+
managerObservation: reference(relay.managerObservation),
|
|
775
|
+
nodeObservation: relayNodeObservation,
|
|
776
|
+
credential: reference(relay.credential),
|
|
777
|
+
acceptedRegistration: reference(relay.acceptedRegistration),
|
|
778
|
+
version: relayVersion,
|
|
779
|
+
},
|
|
780
|
+
spark: {
|
|
781
|
+
nodeId: sparkNodeId,
|
|
782
|
+
credentialGeneration: networkCounter(spark.credentialGeneration),
|
|
783
|
+
reporterSessionId: networkId(spark.reporterSessionId),
|
|
784
|
+
observationSequence: networkCounter(spark.observationSequence),
|
|
785
|
+
observation: sparkObservation,
|
|
786
|
+
bundleVersion: releaseVersion(spark.bundleVersion),
|
|
787
|
+
bundleSourceCommit: (() => {
|
|
788
|
+
requireNetwork(typeof spark.bundleSourceCommit === 'string'
|
|
789
|
+
&& /^[a-f0-9]{40}$/.test(spark.bundleSourceCommit));
|
|
790
|
+
return spark.bundleSourceCommit;
|
|
791
|
+
})(),
|
|
792
|
+
bundleManifestSha256: sha256Hex(spark.bundleManifestSha256),
|
|
793
|
+
unitName: networkId(spark.unitName),
|
|
794
|
+
unitDigest: networkDigest(spark.unitDigest),
|
|
795
|
+
},
|
|
796
|
+
legacy: {
|
|
797
|
+
credential: reference(legacy.credential),
|
|
798
|
+
invalidation: reference(legacy.invalidation),
|
|
799
|
+
oldModeRefusal: reference(legacy.oldModeRefusal),
|
|
800
|
+
configurationCas: reference(legacy.configurationCas),
|
|
801
|
+
sourceOwnerGeneration: networkCounter(legacy.sourceOwnerGeneration),
|
|
802
|
+
sourceSha256: sha256Hex(legacy.sourceSha256),
|
|
803
|
+
sourceDisposition: literal(['retained-inert', 'removed'], legacy.sourceDisposition),
|
|
804
|
+
},
|
|
805
|
+
acceptedAt: networkCounter(value.acceptedAt),
|
|
806
|
+
digest: networkDigest(value.digest),
|
|
807
|
+
};
|
|
808
|
+
});
|
|
809
|
+
export const computeFleetCutoverCoreflowRetirementDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.coreflowRetirementDigestDomain, snapshotFleetCutoverCoreflowRetirementEvidence(valueArg));
|
|
810
|
+
export const validateFleetCutoverCoreflowRetirementEvidence = async (valueArg) => {
|
|
811
|
+
try {
|
|
812
|
+
const value = snapshotFleetCutoverCoreflowRetirementEvidence(valueArg);
|
|
813
|
+
return value.digest === await computeFleetCutoverCoreflowRetirementDigest(value)
|
|
814
|
+
? [] : ['fleet cutover Coreflow retirement digest does not match'];
|
|
815
|
+
}
|
|
816
|
+
catch {
|
|
817
|
+
return ['fleet cutover Coreflow retirement evidence must use its exact canonical schema'];
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
export const snapshotFleetCutoverIngressAuthority = (valueArg) => safe(() => {
|
|
821
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
822
|
+
'id', 'generation', 'clusterId', 'runtime', 'scope', 'targetSet', 'ingressServiceId',
|
|
823
|
+
'assignment', 'session', 'ingressRegistration', 'registrationRouteRevision',
|
|
824
|
+
'legacyIngressAbsence', 'sourcePublication', 'targetPublication', 'portTransfer',
|
|
825
|
+
'routeTableRevision', 'routeTableReadback', 'acceptedAt', 'digest',
|
|
826
|
+
]);
|
|
827
|
+
const clusterId = networkId(value.clusterId);
|
|
828
|
+
const runtime = runtimeReference(value.runtime);
|
|
829
|
+
const targetSet = targetSetReference(value.targetSet);
|
|
830
|
+
const session = runtimeSession(value.session);
|
|
831
|
+
requireNetwork(runtime.id === clusterId && runtime.phase === 'pallet'
|
|
832
|
+
&& targetSet.cloudlyClusterId === clusterId && session.clusterId === clusterId);
|
|
833
|
+
return {
|
|
834
|
+
id: networkId(value.id),
|
|
835
|
+
generation: networkCounter(value.generation),
|
|
836
|
+
clusterId,
|
|
837
|
+
runtime: runtime,
|
|
838
|
+
scope: reference(value.scope),
|
|
839
|
+
targetSet,
|
|
840
|
+
ingressServiceId: networkId(value.ingressServiceId),
|
|
841
|
+
assignment: assignmentReference(value.assignment),
|
|
842
|
+
session,
|
|
843
|
+
ingressRegistration: reference(value.ingressRegistration),
|
|
844
|
+
registrationRouteRevision: value.registrationRouteRevision === null
|
|
845
|
+
? null : nonNegative(value.registrationRouteRevision),
|
|
846
|
+
legacyIngressAbsence: reference(value.legacyIngressAbsence),
|
|
847
|
+
sourcePublication: reference(value.sourcePublication),
|
|
848
|
+
targetPublication: reference(value.targetPublication),
|
|
849
|
+
portTransfer: reference(value.portTransfer),
|
|
850
|
+
routeTableRevision: nonNegative(value.routeTableRevision),
|
|
851
|
+
routeTableReadback: reference(value.routeTableReadback),
|
|
852
|
+
acceptedAt: networkCounter(value.acceptedAt),
|
|
853
|
+
digest: networkDigest(value.digest),
|
|
854
|
+
};
|
|
855
|
+
});
|
|
856
|
+
export const computeFleetCutoverIngressAuthorityDigest = async (valueArg) => canonicalDigest(fleetCutoverContract.ingressAuthorityDigestDomain, snapshotFleetCutoverIngressAuthority(valueArg));
|
|
857
|
+
export const validateFleetCutoverIngressAuthority = async (valueArg) => {
|
|
858
|
+
try {
|
|
859
|
+
const value = snapshotFleetCutoverIngressAuthority(valueArg);
|
|
860
|
+
return value.digest === await computeFleetCutoverIngressAuthorityDigest(value)
|
|
861
|
+
? [] : ['fleet cutover ingress authority digest does not match'];
|
|
862
|
+
}
|
|
863
|
+
catch {
|
|
864
|
+
return ['fleet cutover ingress authority must use its exact canonical schema'];
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
export const isLegalFleetCutoverPhaseTransition = (fromArg, toArg) => fleetCutoverContract.legalPhaseTransitions[fromArg] === toArg;
|
|
868
|
+
export const snapshotFleetCutoverPhaseAdvance = (valueArg) => safe(() => {
|
|
869
|
+
requireNetwork(valueArg !== null && typeof valueArg === 'object');
|
|
870
|
+
const candidate = valueArg;
|
|
871
|
+
const from = literal(['swarm', 'draining', 'switching'], candidate.from);
|
|
872
|
+
const expectedTo = fleetCutoverContract.legalPhaseTransitions[from];
|
|
873
|
+
requireNetwork(candidate.to === expectedTo);
|
|
874
|
+
const extraKeys = from === 'swarm'
|
|
875
|
+
? ['coreflowRetirement']
|
|
876
|
+
: from === 'draining'
|
|
877
|
+
? ['swarmQuiescence', 'heldRuntimeSpecs', 'heldVolumeFences']
|
|
878
|
+
: ['heldRuntimeSpecs', 'heldVolumeFences', 'palletPreparation'];
|
|
879
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
880
|
+
'mutationId', 'clusterId', 'currentRuntime', 'scope', 'targetSet', 'from', 'to', ...extraKeys,
|
|
881
|
+
]);
|
|
882
|
+
const currentRuntime = runtimeReference(value.currentRuntime);
|
|
883
|
+
const clusterId = networkId(value.clusterId);
|
|
884
|
+
const targetSet = targetSetReference(value.targetSet);
|
|
885
|
+
requireNetwork(currentRuntime.id === clusterId && currentRuntime.phase === from
|
|
886
|
+
&& targetSet.cloudlyClusterId === clusterId);
|
|
887
|
+
const base = {
|
|
888
|
+
mutationId: networkId(value.mutationId),
|
|
889
|
+
clusterId,
|
|
890
|
+
currentRuntime,
|
|
891
|
+
scope: reference(value.scope),
|
|
892
|
+
targetSet,
|
|
893
|
+
};
|
|
894
|
+
if (from === 'swarm')
|
|
895
|
+
return {
|
|
896
|
+
...base,
|
|
897
|
+
from,
|
|
898
|
+
to: 'draining',
|
|
899
|
+
coreflowRetirement: reference(value.coreflowRetirement),
|
|
900
|
+
};
|
|
901
|
+
if (from === 'draining')
|
|
902
|
+
return {
|
|
903
|
+
...base,
|
|
904
|
+
from,
|
|
905
|
+
to: 'switching',
|
|
906
|
+
swarmQuiescence: reference(value.swarmQuiescence),
|
|
907
|
+
heldRuntimeSpecs: reference(value.heldRuntimeSpecs),
|
|
908
|
+
heldVolumeFences: reference(value.heldVolumeFences),
|
|
909
|
+
};
|
|
910
|
+
return {
|
|
911
|
+
...base,
|
|
912
|
+
from,
|
|
913
|
+
to: 'pallet',
|
|
914
|
+
heldRuntimeSpecs: reference(value.heldRuntimeSpecs),
|
|
915
|
+
heldVolumeFences: reference(value.heldVolumeFences),
|
|
916
|
+
palletPreparation: reference(value.palletPreparation),
|
|
917
|
+
};
|
|
918
|
+
});
|
|
919
|
+
export const snapshotFleetCutoverRuntimeSpecRelease = (valueArg) => safe(() => {
|
|
920
|
+
requireNetwork(valueArg !== null && typeof valueArg === 'object');
|
|
921
|
+
const kind = literal(['ingress', 'application'], valueArg.kind);
|
|
922
|
+
const evidenceKey = kind === 'ingress' ? 'emptyPublishedPortsPolicy' : 'ingressAuthority';
|
|
923
|
+
const value = networkRecord(captureNetwork(valueArg), [
|
|
924
|
+
'kind', 'mutationId', 'clusterId', 'serviceId', 'expectedSpecRevision', 'runtime', 'scope',
|
|
925
|
+
evidenceKey,
|
|
926
|
+
]);
|
|
927
|
+
const runtime = runtimeReference(value.runtime);
|
|
928
|
+
const clusterId = networkId(value.clusterId);
|
|
929
|
+
requireNetwork(runtime.id === clusterId && runtime.phase === 'pallet');
|
|
930
|
+
const base = {
|
|
931
|
+
kind,
|
|
932
|
+
mutationId: networkId(value.mutationId),
|
|
933
|
+
clusterId,
|
|
934
|
+
serviceId: networkId(value.serviceId),
|
|
935
|
+
expectedSpecRevision: networkCounter(value.expectedSpecRevision),
|
|
936
|
+
runtime: runtime,
|
|
937
|
+
scope: reference(value.scope),
|
|
938
|
+
};
|
|
939
|
+
return kind === 'ingress'
|
|
940
|
+
? { ...base, kind, emptyPublishedPortsPolicy: reference(value.emptyPublishedPortsPolicy) }
|
|
941
|
+
: { ...base, kind, ingressAuthority: reference(value.ingressAuthority) };
|
|
942
|
+
});
|
|
943
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxlZXRjdXRvdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9mbGVldGN1dG92ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFNdEUsT0FBTyxFQUNMLHNCQUFzQixFQUN0Qiw0QkFBNEIsR0FDN0IsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQ0wsY0FBYyxFQUNkLGNBQWMsRUFDZCxhQUFhLEVBQ2IsU0FBUyxFQUNULFdBQVcsRUFDWCxhQUFhLEVBQ2IsYUFBYSxFQUNiLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IsY0FBYyxHQUNmLE1BQU0sK0JBQStCLENBQUM7QUEwYXZDLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDaEQsZUFBZSxFQUFFLEdBQUc7SUFDcEIsWUFBWSxFQUFFLElBQUk7SUFDbEIsWUFBWSxFQUFFLElBQUk7SUFDbEIsd0JBQXdCLEVBQUUsR0FBRztJQUM3QixxQkFBcUIsRUFBRSxFQUFFO0lBQ3pCLHNCQUFzQixFQUFFLEdBQUc7SUFDM0Isc0JBQXNCLEVBQUUsT0FBTztJQUMvQiwrQkFBK0IsRUFBRSxnREFBZ0Q7SUFDakYsK0JBQStCLEVBQUUsZ0RBQWdEO0lBQ2pGLHlCQUF5QixFQUFFLHlDQUF5QztJQUNwRSxnQ0FBZ0MsRUFBRSxpREFBaUQ7SUFDbkYsNkJBQTZCLEVBQUUsOENBQThDO0lBQzdFLDJCQUEyQixFQUFFLDJDQUEyQztJQUN4RSxrQkFBa0IsRUFBRSxpQ0FBaUM7SUFDckQsaUJBQWlCLEVBQUUsZ0NBQWdDO0lBQ25ELHlCQUF5QixFQUFFLHlDQUF5QztJQUNwRSx1QkFBdUIsRUFBRSx1Q0FBdUM7SUFDaEUsNkJBQTZCLEVBQUUsNkNBQTZDO0lBQzVFLDhCQUE4QixFQUFFLDhDQUE4QztJQUM5RSw0QkFBNEIsRUFBRSw0Q0FBNEM7SUFDMUUs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
|