@takodotid/circuit 0.34.2 → 0.35.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/README.md +13 -14
- package/dist/chunks/index-20kcjxjg.js +174 -0
- package/dist/chunks/index-2r4bbhac.js +977 -0
- package/dist/chunks/index-n7w3tg5y.js +149 -0
- package/dist/chunks/new-w3zys5y4.js +172 -0
- package/dist/chunks/server-gzsf5me5.js +259 -0
- package/dist/cli/index.js +11347 -9018
- package/dist/helpers/index.js +594 -0
- package/dist/index.js +9 -28
- package/dist/types/core/{addresses.d.ts → address-space.d.ts} +23 -7
- package/dist/types/core/address.d.ts +44 -0
- package/dist/types/core/cabling.d.ts +41 -0
- package/dist/types/core/cross-checks.d.ts +28 -0
- package/dist/types/core/define.d.ts +25 -3
- package/dist/types/core/project-files.d.ts +12 -0
- package/dist/types/core/schema-docs.d.ts +13 -4
- package/dist/types/core/secrets.d.ts +62 -21
- package/dist/types/core/{graph.d.ts → topology.d.ts} +32 -12
- package/dist/types/core/utils.d.ts +8 -0
- package/dist/types/core/validator.d.ts +19 -0
- package/dist/types/helpers/bgp.d.ts +97 -0
- package/dist/types/helpers/checks.d.ts +32 -0
- package/dist/types/helpers/exchange.d.ts +49 -0
- package/dist/types/helpers/filters.d.ts +51 -0
- package/dist/types/helpers/index.d.ts +10 -0
- package/dist/types/helpers/route-server.d.ts +52 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/integrations/librenms.d.ts +60 -0
- package/dist/types/integrations/netbox.d.ts +89 -0
- package/dist/types/integrations/peeringdb.d.ts +24 -0
- package/dist/types/integrations/prometheus.d.ts +24 -0
- package/dist/types/integrations/registries.d.ts +8 -0
- package/dist/types/platforms/bgp-wait.d.ts +18 -0
- package/dist/types/platforms/catalog.d.ts +109 -0
- package/dist/types/platforms/derive.d.ts +17 -0
- package/dist/types/platforms/fortios/firewall.d.ts +45 -0
- package/dist/types/platforms/fortios/index.d.ts +134 -0
- package/dist/types/platforms/fortios/names.d.ts +52 -0
- package/dist/types/platforms/fortios/plan.d.ts +104 -0
- package/dist/types/platforms/fortios/render.d.ts +75 -0
- package/dist/types/platforms/fortios/routing.d.ts +56 -0
- package/dist/types/platforms/fortios/tree.d.ts +37 -0
- package/dist/types/platforms/index.d.ts +13 -0
- package/dist/types/platforms/junos/bgp.d.ts +44 -0
- package/dist/types/platforms/junos/index.d.ts +114 -0
- package/dist/types/platforms/junos/render.d.ts +154 -0
- package/dist/types/platforms/line-diff.d.ts +67 -0
- package/dist/types/platforms/platform.d.ts +120 -0
- package/dist/types/platforms/raisecom-ros/index.d.ts +71 -0
- package/dist/types/platforms/raisecom-ros/render.d.ts +41 -0
- package/dist/types/platforms/routeros/export.d.ts +59 -0
- package/dist/types/platforms/routeros/index.d.ts +96 -0
- package/dist/types/{adapters/devices → platforms}/routeros/models.d.ts +4 -0
- package/dist/types/platforms/routeros/plan.d.ts +54 -0
- package/dist/types/platforms/routeros/render.d.ts +240 -0
- package/dist/types/platforms/vrp/index.d.ts +83 -0
- package/dist/types/platforms/vrp/render.d.ts +96 -0
- package/dist/types/schema/common.d.ts +12 -6
- package/dist/types/schema/index.d.ts +1 -0
- package/dist/types/schema/interfaces.d.ts +14 -6
- package/dist/types/schema/policy.d.ts +18 -10
- package/dist/types/schema/routing.d.ts +14 -1
- package/dist/types/schema/system.d.ts +16 -6
- package/dist/types/schema/time-zones.d.ts +2 -0
- package/dist/types/transport/console.d.ts +79 -23
- package/dist/types/transport/path-check.d.ts +32 -0
- package/dist/types/transport/ssh.d.ts +17 -15
- package/package.json +17 -11
- package/src/cli/graph-format.ts +91 -0
- package/src/cli/index.ts +1074 -484
- package/src/cli/new.ts +208 -175
- package/src/cli/rename.ts +97 -91
- package/src/core/address-space.ts +320 -0
- package/src/core/address.ts +202 -0
- package/src/core/cabling.ts +154 -0
- package/src/core/cross-checks.ts +364 -0
- package/src/core/define.ts +26 -3
- package/src/core/project-files.ts +35 -0
- package/src/core/schema-docs.ts +138 -130
- package/src/core/secrets.ts +170 -76
- package/src/core/topology.ts +656 -0
- package/src/core/utils.ts +37 -0
- package/src/core/validator.ts +407 -0
- package/src/helpers/bgp.ts +301 -0
- package/src/helpers/checks.ts +178 -0
- package/src/helpers/exchange.ts +117 -0
- package/src/helpers/filters.ts +107 -0
- package/src/helpers/index.ts +12 -0
- package/src/helpers/route-server.ts +212 -0
- package/src/index.ts +6 -3
- package/src/integrations/librenms.ts +291 -0
- package/src/integrations/netbox.ts +620 -0
- package/src/integrations/peeringdb.ts +173 -0
- package/src/integrations/prometheus.ts +90 -0
- package/src/integrations/registries.ts +25 -0
- package/src/platforms/bgp-wait.ts +41 -0
- package/src/platforms/catalog.ts +69 -0
- package/src/platforms/derive.ts +117 -0
- package/src/{adapters/devices → platforms}/fortios/TRAPS.md +6 -0
- package/src/platforms/fortios/firewall.ts +377 -0
- package/src/platforms/fortios/index.ts +1060 -0
- package/src/platforms/fortios/names.ts +130 -0
- package/src/platforms/fortios/plan.ts +929 -0
- package/src/platforms/fortios/render.ts +779 -0
- package/src/platforms/fortios/routing.ts +476 -0
- package/src/platforms/fortios/tree.ts +129 -0
- package/src/platforms/index.ts +36 -0
- package/src/{adapters/devices → platforms}/junos/TRAPS.md +8 -0
- package/src/platforms/junos/bgp.ts +293 -0
- package/src/platforms/junos/index.ts +1006 -0
- package/src/platforms/junos/render.ts +967 -0
- package/src/platforms/line-diff.ts +244 -0
- package/src/platforms/platform.ts +122 -0
- package/src/platforms/raisecom-ros/TRAPS.md +40 -0
- package/src/platforms/raisecom-ros/index.ts +731 -0
- package/src/platforms/raisecom-ros/render.ts +328 -0
- package/src/{adapters/devices → platforms}/routeros/TRAPS.md +16 -2
- package/src/platforms/routeros/export.ts +342 -0
- package/src/platforms/routeros/index.ts +636 -0
- package/src/{adapters/devices → platforms}/routeros/models.ts +2 -0
- package/src/platforms/routeros/plan.ts +444 -0
- package/src/platforms/routeros/render.ts +1483 -0
- package/src/platforms/vrp/TRAPS.md +45 -0
- package/src/platforms/vrp/index.ts +652 -0
- package/src/platforms/vrp/render.ts +615 -0
- package/src/schema/common.ts +15 -6
- package/src/schema/index.ts +1 -0
- package/src/schema/interfaces.ts +15 -5
- package/src/schema/policy.ts +22 -10
- package/src/schema/routing.ts +16 -1
- package/src/schema/system.ts +16 -6
- package/src/schema/time-zones.ts +482 -0
- package/src/studio/data.ts +172 -168
- package/src/studio/git.ts +95 -90
- package/src/studio/public/app.js +161 -150
- package/src/studio/public/compare.js +219 -212
- package/src/studio/public/diff.js +77 -75
- package/src/studio/public/dom.js +118 -108
- package/src/studio/public/evaluate.js +584 -545
- package/src/studio/public/export.js +120 -118
- package/src/studio/public/graph.js +1343 -1266
- package/src/studio/public/net.js +115 -109
- package/src/studio/public/tables.js +1135 -1083
- package/src/studio/public/tools.js +561 -529
- package/src/studio/server.ts +202 -196
- package/src/transport/console.ts +363 -271
- package/src/transport/path-check.ts +91 -0
- package/src/transport/ssh.ts +98 -94
- package/templates/colocation/checks.ts +11 -6
- package/templates/colocation/edge-01.ts +9 -9
- package/templates/colocation/routing.ts +2 -2
- package/templates/colocation/tenancy.ts +3 -3
- package/templates/colocation/tor-01.ts +3 -3
- package/templates/edge-router/checks.ts +4 -4
- package/templates/edge-router/edge-01.ts +5 -5
- package/templates/edge-router/routing.ts +2 -2
- package/templates/project/AGENTS.md +5 -1
- package/templates/single-site/checks.ts +2 -2
- package/dist/chunks/index-47debt16.js +0 -956
- package/dist/chunks/index-v8zgr7wm.js +0 -128
- package/dist/chunks/new-ny89s7y7.js +0 -166
- package/dist/chunks/server-tjbb3rqc.js +0 -251
- package/dist/presets/index.js +0 -394
- package/dist/types/adapters/devices/catalog.d.ts +0 -86
- package/dist/types/adapters/devices/derive.d.ts +0 -7
- package/dist/types/adapters/devices/fortios/firewall.d.ts +0 -23
- package/dist/types/adapters/devices/fortios/index.d.ts +0 -58
- package/dist/types/adapters/devices/fortios/names.d.ts +0 -48
- package/dist/types/adapters/devices/fortios/plan.d.ts +0 -28
- package/dist/types/adapters/devices/fortios/render.d.ts +0 -38
- package/dist/types/adapters/devices/fortios/routing.d.ts +0 -32
- package/dist/types/adapters/devices/fortios/tree.d.ts +0 -33
- package/dist/types/adapters/devices/index.d.ts +0 -3
- package/dist/types/adapters/devices/junos/bgp.d.ts +0 -11
- package/dist/types/adapters/devices/junos/index.d.ts +0 -42
- package/dist/types/adapters/devices/junos/render.d.ts +0 -52
- package/dist/types/adapters/devices/lines.d.ts +0 -56
- package/dist/types/adapters/devices/raisecom-ros/index.d.ts +0 -28
- package/dist/types/adapters/devices/routeros/export.d.ts +0 -39
- package/dist/types/adapters/devices/routeros/index.d.ts +0 -30
- package/dist/types/adapters/devices/routeros/plan.d.ts +0 -4
- package/dist/types/adapters/devices/routeros/render.d.ts +0 -100
- package/dist/types/adapters/devices/types.d.ts +0 -40
- package/dist/types/adapters/devices/vrp/index.d.ts +0 -27
- package/dist/types/adapters/registries/index.d.ts +0 -3
- package/dist/types/adapters/registries/librenms.d.ts +0 -15
- package/dist/types/adapters/registries/peeringdb.d.ts +0 -16
- package/dist/types/adapters/registries/prometheus.d.ts +0 -16
- package/dist/types/core/across.d.ts +0 -4
- package/dist/types/core/addr.d.ts +0 -34
- package/dist/types/core/files.d.ts +0 -6
- package/dist/types/core/merge.d.ts +0 -4
- package/dist/types/core/time.d.ts +0 -2
- package/dist/types/core/validate.d.ts +0 -2
- package/dist/types/presets/index.d.ts +0 -183
- package/src/adapters/devices/catalog.ts +0 -41
- package/src/adapters/devices/derive.ts +0 -59
- package/src/adapters/devices/fortios/firewall.ts +0 -362
- package/src/adapters/devices/fortios/index.ts +0 -923
- package/src/adapters/devices/fortios/names.ts +0 -115
- package/src/adapters/devices/fortios/plan.ts +0 -888
- package/src/adapters/devices/fortios/render.ts +0 -768
- package/src/adapters/devices/fortios/routing.ts +0 -444
- package/src/adapters/devices/fortios/tree.ts +0 -121
- package/src/adapters/devices/index.ts +0 -9
- package/src/adapters/devices/junos/bgp.ts +0 -269
- package/src/adapters/devices/junos/index.ts +0 -862
- package/src/adapters/devices/junos/render.ts +0 -872
- package/src/adapters/devices/lines.ts +0 -212
- package/src/adapters/devices/raisecom-ros/TRAPS.md +0 -25
- package/src/adapters/devices/raisecom-ros/index.ts +0 -693
- package/src/adapters/devices/routeros/export.ts +0 -321
- package/src/adapters/devices/routeros/index.ts +0 -346
- package/src/adapters/devices/routeros/plan.ts +0 -398
- package/src/adapters/devices/routeros/render.ts +0 -1490
- package/src/adapters/devices/types.ts +0 -38
- package/src/adapters/devices/vrp/TRAPS.md +0 -26
- package/src/adapters/devices/vrp/index.ts +0 -865
- package/src/adapters/registries/index.ts +0 -19
- package/src/adapters/registries/librenms.ts +0 -92
- package/src/adapters/registries/peeringdb.ts +0 -169
- package/src/adapters/registries/prometheus.ts +0 -71
- package/src/cli/graph.ts +0 -89
- package/src/core/across.ts +0 -350
- package/src/core/addr.ts +0 -174
- package/src/core/addresses.ts +0 -316
- package/src/core/files.ts +0 -32
- package/src/core/graph.ts +0 -640
- package/src/core/merge.ts +0 -19
- package/src/core/time.ts +0 -15
- package/src/core/validate.ts +0 -348
- package/src/presets/index.ts +0 -579
- /package/dist/types/{adapters/devices → platforms}/fortios/models.d.ts +0 -0
- /package/dist/types/{adapters/devices → platforms}/junos/models.d.ts +0 -0
- /package/dist/types/{adapters/devices → platforms}/raisecom-ros/models.d.ts +0 -0
- /package/dist/types/{adapters/devices → platforms}/vrp/models.d.ts +0 -0
- /package/src/{adapters/devices → platforms}/fortios/models.ts +0 -0
- /package/src/{adapters/devices → platforms}/junos/models.ts +0 -0
- /package/src/{adapters/devices → platforms}/raisecom-ros/models.ts +0 -0
- /package/src/{adapters/devices → platforms}/vrp/models.ts +0 -0
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
// Convergence for platforms whose configuration is a list of lines in nested blocks, such as `interface X` holding its settings. A line the render does not hold is undone, so the device ends up holding exactly the render.
|
|
2
|
-
|
|
3
|
-
import type { Plan, Step } from "./types";
|
|
4
|
-
|
|
5
|
-
export type Dialect = {
|
|
6
|
-
/** A line at the margin that opens a block, for platforms that do not indent a block's lines. */
|
|
7
|
-
block: RegExp;
|
|
8
|
-
/** Whether a block's lines are indented under it. When they are, any line followed by deeper lines opens a block. */
|
|
9
|
-
indented: boolean;
|
|
10
|
-
/** A line at the margin that closes every open block. */
|
|
11
|
-
terminator: string;
|
|
12
|
-
/** Lines that describe the device rather than configure it, or that the platform prints whatever is set. */
|
|
13
|
-
ignore: (line: string) => boolean;
|
|
14
|
-
/** The command that removes a line. */
|
|
15
|
-
undo: (line: string) => string;
|
|
16
|
-
/** Leaves one level of block. */
|
|
17
|
-
leave: string;
|
|
18
|
-
/** Lines sent before the undos of their block, because the platform refuses an undo until they are in place. */
|
|
19
|
-
first?: RegExp;
|
|
20
|
-
/** A line in the form both sides compare in, for example a secret the device prints as a cipher. */
|
|
21
|
-
canon?: (line: string) => string;
|
|
22
|
-
/** Where a block is sent among the others, lowest first, so that nothing is referenced before it exists. In the order they differ when absent. */
|
|
23
|
-
order?: (path: string[]) => number;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/** One line, with the blocks it sits in, outermost first. */
|
|
27
|
-
export type Entry = { path: string[]; line: string };
|
|
28
|
-
|
|
29
|
-
/** How deep a line is indented. */
|
|
30
|
-
const indentOf = (raw: string) => raw.length - raw.trimStart().length;
|
|
31
|
-
|
|
32
|
-
export function entries(text: string, dialect: Dialect): Entry[] {
|
|
33
|
-
const lines = text
|
|
34
|
-
.replace(/\r/g, "")
|
|
35
|
-
.split("\n")
|
|
36
|
-
.filter((raw) => raw.trim() !== "");
|
|
37
|
-
const result: Entry[] = [];
|
|
38
|
-
const open: { indent: number; header: string }[] = [];
|
|
39
|
-
|
|
40
|
-
for (let i = 0; i < lines.length; i++) {
|
|
41
|
-
const raw = lines[i]!;
|
|
42
|
-
const indent = indentOf(raw);
|
|
43
|
-
const line = raw.trim().replace(/\s+/g, " ");
|
|
44
|
-
|
|
45
|
-
if (line === dialect.terminator) {
|
|
46
|
-
if (indent === 0) open.length = 0;
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (dialect.ignore(line)) continue;
|
|
51
|
-
|
|
52
|
-
if (dialect.indented) {
|
|
53
|
-
while (open.length && open.at(-1)!.indent >= indent) open.pop();
|
|
54
|
-
} else if (indent === 0 && dialect.block.test(line)) {
|
|
55
|
-
open.length = 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
result.push({ path: open.map((block) => block.header), line });
|
|
59
|
-
|
|
60
|
-
const isContent = (candidate: string) => candidate.trim() !== dialect.terminator && !dialect.ignore(candidate.trim());
|
|
61
|
-
const nextLine = lines.slice(i + 1).find(isContent);
|
|
62
|
-
|
|
63
|
-
const opensBlock = dialect.indented
|
|
64
|
-
? nextLine !== undefined && indentOf(nextLine) > indent
|
|
65
|
-
: indent === 0 && dialect.block.test(line);
|
|
66
|
-
|
|
67
|
-
if (opensBlock) open.push({ indent, header: line });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** The part of a line that names what it sets: `rule 5`, a free-text keyword, or the line up to its value. Two lines with one head are one setting with two values. */
|
|
74
|
-
export function head(line: string): string {
|
|
75
|
-
const rule = /^rule \d+/.exec(line);
|
|
76
|
-
if (rule) return rule[0];
|
|
77
|
-
|
|
78
|
-
if (/^(description|name) /.test(line)) return line.split(" ")[0]!;
|
|
79
|
-
|
|
80
|
-
const words = line.split(" ");
|
|
81
|
-
return words.slice(0, Math.max(1, words.length - 1)).join(" ");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** What changes inside one block. */
|
|
85
|
-
export type Group = { path: string[]; remove: string[]; add: string[] };
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* What differs, by block.
|
|
89
|
-
*
|
|
90
|
-
* A device line replaced by a desired line with the same head is not undone; sending the new one is enough. A block the render does not hold goes with its header, and its lines with it.
|
|
91
|
-
*/
|
|
92
|
-
export function compare(desired: string, current: string, dialect: Dialect): Group[] {
|
|
93
|
-
const canon = dialect.canon ?? ((line: string) => line);
|
|
94
|
-
const keyOf = (entry: Entry) => [...entry.path, canon(entry.line)].join("\u0000");
|
|
95
|
-
const pathKey = (path: string[]) => path.join("\u0000");
|
|
96
|
-
|
|
97
|
-
const wanted = entries(desired, dialect);
|
|
98
|
-
const existing = entries(current, dialect);
|
|
99
|
-
const wantedKeys = new Set(wanted.map(keyOf));
|
|
100
|
-
const existingKeys = new Set(existing.map(keyOf));
|
|
101
|
-
const wantedBlocks = new Set(wanted.map((entry) => pathKey([...entry.path, entry.line])));
|
|
102
|
-
|
|
103
|
-
const groups = new Map<string, Group>();
|
|
104
|
-
const groupFor = (path: string[]) => {
|
|
105
|
-
const key = pathKey(path);
|
|
106
|
-
if (!groups.has(key)) groups.set(key, { path, remove: [], add: [] });
|
|
107
|
-
return groups.get(key)!;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
for (const entry of wanted) {
|
|
111
|
-
if (existingKeys.has(keyOf(entry))) continue;
|
|
112
|
-
|
|
113
|
-
// A header goes with its block's own step, never on its own.
|
|
114
|
-
const ownBlock = pathKey([...entry.path, entry.line]);
|
|
115
|
-
const opensBlock = wanted.some((other) => {
|
|
116
|
-
const deeper = other.path.length > entry.path.length;
|
|
117
|
-
return deeper && pathKey(other.path.slice(0, entry.path.length + 1)) === ownBlock;
|
|
118
|
-
});
|
|
119
|
-
if (opensBlock) continue;
|
|
120
|
-
|
|
121
|
-
groupFor(entry.path).add.push(entry.line);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Undone in reverse order, so a line is undone before the line it depends on.
|
|
125
|
-
for (const entry of [...existing].reverse()) {
|
|
126
|
-
if (wantedKeys.has(keyOf(entry))) continue;
|
|
127
|
-
|
|
128
|
-
// Inside a block the render does not hold: undoing the header removes it.
|
|
129
|
-
const insideRemovedBlock = entry.path.some((_, depth) => {
|
|
130
|
-
const enclosing = pathKey(entry.path.slice(0, depth + 1));
|
|
131
|
-
return !wantedBlocks.has(enclosing);
|
|
132
|
-
});
|
|
133
|
-
if (insideRemovedBlock) continue;
|
|
134
|
-
|
|
135
|
-
const replaced = wanted.some((other) => {
|
|
136
|
-
const sameBlock = pathKey(other.path) === pathKey(entry.path);
|
|
137
|
-
const isNew = !existingKeys.has(keyOf(other));
|
|
138
|
-
return sameBlock && isNew && head(other.line) === head(entry.line);
|
|
139
|
-
});
|
|
140
|
-
if (!replaced) groupFor(entry.path).remove.push(entry.line);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return [...groups.values()].filter((group) => group.add.length || group.remove.length);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Replace a changed VLAN list line with only what changed.
|
|
148
|
-
*
|
|
149
|
-
* A platform keeps its VLANs as one line, such as `vlan batch 10 20 to 30`. Undoing the old line would delete VLANs still in use, so the plan adds the new IDs and removes the gone ones instead.
|
|
150
|
-
*/
|
|
151
|
-
export function vlanListChange(
|
|
152
|
-
groups: Group[],
|
|
153
|
-
prefix: string,
|
|
154
|
-
parse: (line: string) => number[],
|
|
155
|
-
format: (ids: number[]) => string[],
|
|
156
|
-
removal: (ids: number[]) => string[]
|
|
157
|
-
): void {
|
|
158
|
-
const top = groups.find((group) => group.path.length === 0);
|
|
159
|
-
if (!top) return;
|
|
160
|
-
|
|
161
|
-
const old = top.remove.find((line) => line.startsWith(prefix));
|
|
162
|
-
const fresh = top.add.find((line) => line.startsWith(prefix));
|
|
163
|
-
if (!old && !fresh) return;
|
|
164
|
-
|
|
165
|
-
const before = old ? parse(old) : [];
|
|
166
|
-
const after = fresh ? parse(fresh) : [];
|
|
167
|
-
|
|
168
|
-
top.remove = top.remove.filter((line) => line !== old);
|
|
169
|
-
top.add = top.add.filter((line) => line !== fresh);
|
|
170
|
-
|
|
171
|
-
const added = after.filter((id) => !before.includes(id));
|
|
172
|
-
const removed = before.filter((id) => !after.includes(id));
|
|
173
|
-
|
|
174
|
-
// New VLANs exist before anything uses them; gone ones go after.
|
|
175
|
-
if (added.length) top.add.unshift(...format(added));
|
|
176
|
-
if (removed.length) top.remove.push(...removal(removed));
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Commands a platform needs around one group, such as releasing a binding before a change and restoring it after. */
|
|
180
|
-
export type Around = (group: Group) => { before: string[]; after: string[] };
|
|
181
|
-
|
|
182
|
-
const nothingAround: Around = () => ({ before: [], after: [] });
|
|
183
|
-
|
|
184
|
-
/** The steps for the groups: enter each block of the path, undo, add, then leave each level. */
|
|
185
|
-
export function steps(groups: Group[], dialect: Dialect, around: Around = nothingAround): Plan["steps"] {
|
|
186
|
-
const rank = dialect.order ?? (() => 0);
|
|
187
|
-
const ordered = [...groups].sort((a, b) => rank(a.path) - rank(b.path));
|
|
188
|
-
|
|
189
|
-
return ordered.map((group): Step => {
|
|
190
|
-
const { before, after } = around(group);
|
|
191
|
-
|
|
192
|
-
const early = group.add.filter((line) => dialect.first?.test(line));
|
|
193
|
-
const late = group.add.filter((line) => !early.includes(line));
|
|
194
|
-
|
|
195
|
-
// A block header sent on its own, such as an empty `bfd`, enters its view; it is left at once so the next line is not sent into it.
|
|
196
|
-
const added = late.flatMap((line) => (dialect.block.test(line) ? [line, dialect.leave] : [line]));
|
|
197
|
-
|
|
198
|
-
const inner = [...early, ...group.remove.map(dialect.undo), ...added];
|
|
199
|
-
const leave = group.path.map(() => dialect.leave);
|
|
200
|
-
|
|
201
|
-
return {
|
|
202
|
-
title: group.path.join(" > ") || "(top level)",
|
|
203
|
-
show: [...group.remove.map((line) => `- ${line}`), ...group.add.map((line) => `+ ${line}`)],
|
|
204
|
-
send: [...before, ...group.path, ...inner, ...leave, ...after],
|
|
205
|
-
};
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const STORED_CREDENTIAL = /(password (?:irreversible-)?cipher|community read cipher|^snmp-server community)( +)\S+/gm;
|
|
210
|
-
|
|
211
|
-
/** A device prints stored credentials as ciphers. They never leave the read. */
|
|
212
|
-
export const scrub = (text: string) => text.replace(STORED_CREDENTIAL, "$1$2<redacted>");
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Raisecom ROS traps
|
|
2
|
-
|
|
3
|
-
Behaviour that looks like something else. Each one has been hit on a RAX721 running ROS 6.5.2.
|
|
4
|
-
|
|
5
|
-
- Commands apply as they arrive and persist only on `write`.
|
|
6
|
-
- The SSH server offers only an `ssh-rsa` host key. The adapter allows it for this platform alone; key exchange, cipher and MAC still negotiate modern ones.
|
|
7
|
-
- `show running-config` stops about halfway with no error unless `terminal page-break disable` is sent first and the read waits several seconds of silence.
|
|
8
|
-
- A `?` sent by a script is executed. Once it applied an address with a /8 mask.
|
|
9
|
-
- An access-list cannot change while any service uses it: `ACL 1000 is in use`. Every service that uses it is unbound first and bound again after. `no ssh2 access-list` needs the list number.
|
|
10
|
-
- `portswitch`, `switchport trunk allowed vlan` and `switchport mode` ask for `y` and do nothing without it, except when they need no confirming: `switchport mode trunk` on a port leaving access mode answers `Set successfully` at once, and a `y` sent after it is refused, `Error input`.
|
|
11
|
-
- A VLAN is removed with `no vlan <id>`, not `no create vlan`.
|
|
12
|
-
- `no storm-control mode` is refused with `Error input`. The modes are `kbps`, the default, which prints nothing, and `pps`; leaving `pps` is setting `kbps`.
|
|
13
|
-
- A port's speed or duplex set to something else and back to auto prints `speed auto` and `duplex auto` from then on, though auto is the default. `no duplex auto` is refused with `Error input`.
|
|
14
|
-
- Tab after a word the CLI does not know answers `Error input`, as if the line were sent. Like `?`, it is not a safe way to explore.
|
|
15
|
-
- The factory account `raisecom` cannot be removed and its service type cannot change. Only its password is ours.
|
|
16
|
-
- Factory SNMP communities survive hardening, and `private` can write. The render removes both.
|
|
17
|
-
- Several commands are not the usual spelling: `terminal page-break disable`, `telnet-server disable`, `ip rarp server disable`.
|
|
18
|
-
- An access-list description takes one word. A space is refused with `Error input`.
|
|
19
|
-
- The out-of-band port `fastethernet 1/0/1` cannot be shut down and is not in the catalog.
|
|
20
|
-
- A LAG is `interface port-channel N`. LACP is its default and prints nothing; a static LAG prints `mode manual`. The LAG takes layer 2 settings only after `portswitch`, and a port joins with `portswitch` then `port-channel N`.
|
|
21
|
-
- An SNMPv3 user prints as localized keys, `authkey sha <hex> privkey aes128 <hex>`, which authenticate as well as the passphrase. The read redacts them. An access group prints a `notify internet` it was not given. A user's group is removed with `no snmp-server group user <user> usm`.
|
|
22
|
-
- A VRRP group is enabled once it has an address and preempts unless `no vrrp N preempt`. `no vrrp N ip <address>` removes the whole group.
|
|
23
|
-
- OSPF settings for an interface sit on the interface, `ip ospf cost`, `ip ospf network ptp`, `ip ospf passive-interface enable`; passive is undone with `... disable`, not `no`.
|
|
24
|
-
- `create vlan <list> active` has every VLAN on one line. A change creates only the new VLANs and removes each one that is gone with `no vlan <id>`.
|
|
25
|
-
- An access-list rule is not replaced by one with the same number: the device answers `Set unsuccessfully.` and keeps the old rule. The old one is removed first. `no rule N` answers slowly, after a second or more.
|