@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.
Files changed (240) hide show
  1. package/README.md +13 -14
  2. package/dist/chunks/index-20kcjxjg.js +174 -0
  3. package/dist/chunks/index-2r4bbhac.js +977 -0
  4. package/dist/chunks/index-n7w3tg5y.js +149 -0
  5. package/dist/chunks/new-w3zys5y4.js +172 -0
  6. package/dist/chunks/server-gzsf5me5.js +259 -0
  7. package/dist/cli/index.js +11347 -9018
  8. package/dist/helpers/index.js +594 -0
  9. package/dist/index.js +9 -28
  10. package/dist/types/core/{addresses.d.ts → address-space.d.ts} +23 -7
  11. package/dist/types/core/address.d.ts +44 -0
  12. package/dist/types/core/cabling.d.ts +41 -0
  13. package/dist/types/core/cross-checks.d.ts +28 -0
  14. package/dist/types/core/define.d.ts +25 -3
  15. package/dist/types/core/project-files.d.ts +12 -0
  16. package/dist/types/core/schema-docs.d.ts +13 -4
  17. package/dist/types/core/secrets.d.ts +62 -21
  18. package/dist/types/core/{graph.d.ts → topology.d.ts} +32 -12
  19. package/dist/types/core/utils.d.ts +8 -0
  20. package/dist/types/core/validator.d.ts +19 -0
  21. package/dist/types/helpers/bgp.d.ts +97 -0
  22. package/dist/types/helpers/checks.d.ts +32 -0
  23. package/dist/types/helpers/exchange.d.ts +49 -0
  24. package/dist/types/helpers/filters.d.ts +51 -0
  25. package/dist/types/helpers/index.d.ts +10 -0
  26. package/dist/types/helpers/route-server.d.ts +52 -0
  27. package/dist/types/index.d.ts +5 -3
  28. package/dist/types/integrations/librenms.d.ts +60 -0
  29. package/dist/types/integrations/netbox.d.ts +89 -0
  30. package/dist/types/integrations/peeringdb.d.ts +24 -0
  31. package/dist/types/integrations/prometheus.d.ts +24 -0
  32. package/dist/types/integrations/registries.d.ts +8 -0
  33. package/dist/types/platforms/bgp-wait.d.ts +18 -0
  34. package/dist/types/platforms/catalog.d.ts +109 -0
  35. package/dist/types/platforms/derive.d.ts +17 -0
  36. package/dist/types/platforms/fortios/firewall.d.ts +45 -0
  37. package/dist/types/platforms/fortios/index.d.ts +134 -0
  38. package/dist/types/platforms/fortios/names.d.ts +52 -0
  39. package/dist/types/platforms/fortios/plan.d.ts +104 -0
  40. package/dist/types/platforms/fortios/render.d.ts +75 -0
  41. package/dist/types/platforms/fortios/routing.d.ts +56 -0
  42. package/dist/types/platforms/fortios/tree.d.ts +37 -0
  43. package/dist/types/platforms/index.d.ts +13 -0
  44. package/dist/types/platforms/junos/bgp.d.ts +44 -0
  45. package/dist/types/platforms/junos/index.d.ts +114 -0
  46. package/dist/types/platforms/junos/render.d.ts +154 -0
  47. package/dist/types/platforms/line-diff.d.ts +67 -0
  48. package/dist/types/platforms/platform.d.ts +120 -0
  49. package/dist/types/platforms/raisecom-ros/index.d.ts +71 -0
  50. package/dist/types/platforms/raisecom-ros/render.d.ts +41 -0
  51. package/dist/types/platforms/routeros/export.d.ts +59 -0
  52. package/dist/types/platforms/routeros/index.d.ts +96 -0
  53. package/dist/types/{adapters/devices → platforms}/routeros/models.d.ts +4 -0
  54. package/dist/types/platforms/routeros/plan.d.ts +54 -0
  55. package/dist/types/platforms/routeros/render.d.ts +240 -0
  56. package/dist/types/platforms/vrp/index.d.ts +83 -0
  57. package/dist/types/platforms/vrp/render.d.ts +96 -0
  58. package/dist/types/schema/common.d.ts +12 -6
  59. package/dist/types/schema/index.d.ts +1 -0
  60. package/dist/types/schema/interfaces.d.ts +14 -6
  61. package/dist/types/schema/policy.d.ts +18 -10
  62. package/dist/types/schema/routing.d.ts +14 -1
  63. package/dist/types/schema/system.d.ts +16 -6
  64. package/dist/types/schema/time-zones.d.ts +2 -0
  65. package/dist/types/transport/console.d.ts +79 -23
  66. package/dist/types/transport/path-check.d.ts +32 -0
  67. package/dist/types/transport/ssh.d.ts +17 -15
  68. package/package.json +17 -11
  69. package/src/cli/graph-format.ts +91 -0
  70. package/src/cli/index.ts +1074 -484
  71. package/src/cli/new.ts +208 -175
  72. package/src/cli/rename.ts +97 -91
  73. package/src/core/address-space.ts +320 -0
  74. package/src/core/address.ts +202 -0
  75. package/src/core/cabling.ts +154 -0
  76. package/src/core/cross-checks.ts +364 -0
  77. package/src/core/define.ts +26 -3
  78. package/src/core/project-files.ts +35 -0
  79. package/src/core/schema-docs.ts +138 -130
  80. package/src/core/secrets.ts +170 -76
  81. package/src/core/topology.ts +656 -0
  82. package/src/core/utils.ts +37 -0
  83. package/src/core/validator.ts +407 -0
  84. package/src/helpers/bgp.ts +301 -0
  85. package/src/helpers/checks.ts +178 -0
  86. package/src/helpers/exchange.ts +117 -0
  87. package/src/helpers/filters.ts +107 -0
  88. package/src/helpers/index.ts +12 -0
  89. package/src/helpers/route-server.ts +212 -0
  90. package/src/index.ts +6 -3
  91. package/src/integrations/librenms.ts +291 -0
  92. package/src/integrations/netbox.ts +620 -0
  93. package/src/integrations/peeringdb.ts +173 -0
  94. package/src/integrations/prometheus.ts +90 -0
  95. package/src/integrations/registries.ts +25 -0
  96. package/src/platforms/bgp-wait.ts +41 -0
  97. package/src/platforms/catalog.ts +69 -0
  98. package/src/platforms/derive.ts +117 -0
  99. package/src/{adapters/devices → platforms}/fortios/TRAPS.md +6 -0
  100. package/src/platforms/fortios/firewall.ts +377 -0
  101. package/src/platforms/fortios/index.ts +1060 -0
  102. package/src/platforms/fortios/names.ts +130 -0
  103. package/src/platforms/fortios/plan.ts +929 -0
  104. package/src/platforms/fortios/render.ts +779 -0
  105. package/src/platforms/fortios/routing.ts +476 -0
  106. package/src/platforms/fortios/tree.ts +129 -0
  107. package/src/platforms/index.ts +36 -0
  108. package/src/{adapters/devices → platforms}/junos/TRAPS.md +8 -0
  109. package/src/platforms/junos/bgp.ts +293 -0
  110. package/src/platforms/junos/index.ts +1006 -0
  111. package/src/platforms/junos/render.ts +967 -0
  112. package/src/platforms/line-diff.ts +244 -0
  113. package/src/platforms/platform.ts +122 -0
  114. package/src/platforms/raisecom-ros/TRAPS.md +40 -0
  115. package/src/platforms/raisecom-ros/index.ts +731 -0
  116. package/src/platforms/raisecom-ros/render.ts +328 -0
  117. package/src/{adapters/devices → platforms}/routeros/TRAPS.md +16 -2
  118. package/src/platforms/routeros/export.ts +342 -0
  119. package/src/platforms/routeros/index.ts +636 -0
  120. package/src/{adapters/devices → platforms}/routeros/models.ts +2 -0
  121. package/src/platforms/routeros/plan.ts +444 -0
  122. package/src/platforms/routeros/render.ts +1483 -0
  123. package/src/platforms/vrp/TRAPS.md +45 -0
  124. package/src/platforms/vrp/index.ts +652 -0
  125. package/src/platforms/vrp/render.ts +615 -0
  126. package/src/schema/common.ts +15 -6
  127. package/src/schema/index.ts +1 -0
  128. package/src/schema/interfaces.ts +15 -5
  129. package/src/schema/policy.ts +22 -10
  130. package/src/schema/routing.ts +16 -1
  131. package/src/schema/system.ts +16 -6
  132. package/src/schema/time-zones.ts +482 -0
  133. package/src/studio/data.ts +172 -168
  134. package/src/studio/git.ts +95 -90
  135. package/src/studio/public/app.js +161 -150
  136. package/src/studio/public/compare.js +219 -212
  137. package/src/studio/public/diff.js +77 -75
  138. package/src/studio/public/dom.js +118 -108
  139. package/src/studio/public/evaluate.js +584 -545
  140. package/src/studio/public/export.js +120 -118
  141. package/src/studio/public/graph.js +1343 -1266
  142. package/src/studio/public/net.js +115 -109
  143. package/src/studio/public/tables.js +1135 -1083
  144. package/src/studio/public/tools.js +561 -529
  145. package/src/studio/server.ts +202 -196
  146. package/src/transport/console.ts +363 -271
  147. package/src/transport/path-check.ts +91 -0
  148. package/src/transport/ssh.ts +98 -94
  149. package/templates/colocation/checks.ts +11 -6
  150. package/templates/colocation/edge-01.ts +9 -9
  151. package/templates/colocation/routing.ts +2 -2
  152. package/templates/colocation/tenancy.ts +3 -3
  153. package/templates/colocation/tor-01.ts +3 -3
  154. package/templates/edge-router/checks.ts +4 -4
  155. package/templates/edge-router/edge-01.ts +5 -5
  156. package/templates/edge-router/routing.ts +2 -2
  157. package/templates/project/AGENTS.md +5 -1
  158. package/templates/single-site/checks.ts +2 -2
  159. package/dist/chunks/index-47debt16.js +0 -956
  160. package/dist/chunks/index-v8zgr7wm.js +0 -128
  161. package/dist/chunks/new-ny89s7y7.js +0 -166
  162. package/dist/chunks/server-tjbb3rqc.js +0 -251
  163. package/dist/presets/index.js +0 -394
  164. package/dist/types/adapters/devices/catalog.d.ts +0 -86
  165. package/dist/types/adapters/devices/derive.d.ts +0 -7
  166. package/dist/types/adapters/devices/fortios/firewall.d.ts +0 -23
  167. package/dist/types/adapters/devices/fortios/index.d.ts +0 -58
  168. package/dist/types/adapters/devices/fortios/names.d.ts +0 -48
  169. package/dist/types/adapters/devices/fortios/plan.d.ts +0 -28
  170. package/dist/types/adapters/devices/fortios/render.d.ts +0 -38
  171. package/dist/types/adapters/devices/fortios/routing.d.ts +0 -32
  172. package/dist/types/adapters/devices/fortios/tree.d.ts +0 -33
  173. package/dist/types/adapters/devices/index.d.ts +0 -3
  174. package/dist/types/adapters/devices/junos/bgp.d.ts +0 -11
  175. package/dist/types/adapters/devices/junos/index.d.ts +0 -42
  176. package/dist/types/adapters/devices/junos/render.d.ts +0 -52
  177. package/dist/types/adapters/devices/lines.d.ts +0 -56
  178. package/dist/types/adapters/devices/raisecom-ros/index.d.ts +0 -28
  179. package/dist/types/adapters/devices/routeros/export.d.ts +0 -39
  180. package/dist/types/adapters/devices/routeros/index.d.ts +0 -30
  181. package/dist/types/adapters/devices/routeros/plan.d.ts +0 -4
  182. package/dist/types/adapters/devices/routeros/render.d.ts +0 -100
  183. package/dist/types/adapters/devices/types.d.ts +0 -40
  184. package/dist/types/adapters/devices/vrp/index.d.ts +0 -27
  185. package/dist/types/adapters/registries/index.d.ts +0 -3
  186. package/dist/types/adapters/registries/librenms.d.ts +0 -15
  187. package/dist/types/adapters/registries/peeringdb.d.ts +0 -16
  188. package/dist/types/adapters/registries/prometheus.d.ts +0 -16
  189. package/dist/types/core/across.d.ts +0 -4
  190. package/dist/types/core/addr.d.ts +0 -34
  191. package/dist/types/core/files.d.ts +0 -6
  192. package/dist/types/core/merge.d.ts +0 -4
  193. package/dist/types/core/time.d.ts +0 -2
  194. package/dist/types/core/validate.d.ts +0 -2
  195. package/dist/types/presets/index.d.ts +0 -183
  196. package/src/adapters/devices/catalog.ts +0 -41
  197. package/src/adapters/devices/derive.ts +0 -59
  198. package/src/adapters/devices/fortios/firewall.ts +0 -362
  199. package/src/adapters/devices/fortios/index.ts +0 -923
  200. package/src/adapters/devices/fortios/names.ts +0 -115
  201. package/src/adapters/devices/fortios/plan.ts +0 -888
  202. package/src/adapters/devices/fortios/render.ts +0 -768
  203. package/src/adapters/devices/fortios/routing.ts +0 -444
  204. package/src/adapters/devices/fortios/tree.ts +0 -121
  205. package/src/adapters/devices/index.ts +0 -9
  206. package/src/adapters/devices/junos/bgp.ts +0 -269
  207. package/src/adapters/devices/junos/index.ts +0 -862
  208. package/src/adapters/devices/junos/render.ts +0 -872
  209. package/src/adapters/devices/lines.ts +0 -212
  210. package/src/adapters/devices/raisecom-ros/TRAPS.md +0 -25
  211. package/src/adapters/devices/raisecom-ros/index.ts +0 -693
  212. package/src/adapters/devices/routeros/export.ts +0 -321
  213. package/src/adapters/devices/routeros/index.ts +0 -346
  214. package/src/adapters/devices/routeros/plan.ts +0 -398
  215. package/src/adapters/devices/routeros/render.ts +0 -1490
  216. package/src/adapters/devices/types.ts +0 -38
  217. package/src/adapters/devices/vrp/TRAPS.md +0 -26
  218. package/src/adapters/devices/vrp/index.ts +0 -865
  219. package/src/adapters/registries/index.ts +0 -19
  220. package/src/adapters/registries/librenms.ts +0 -92
  221. package/src/adapters/registries/peeringdb.ts +0 -169
  222. package/src/adapters/registries/prometheus.ts +0 -71
  223. package/src/cli/graph.ts +0 -89
  224. package/src/core/across.ts +0 -350
  225. package/src/core/addr.ts +0 -174
  226. package/src/core/addresses.ts +0 -316
  227. package/src/core/files.ts +0 -32
  228. package/src/core/graph.ts +0 -640
  229. package/src/core/merge.ts +0 -19
  230. package/src/core/time.ts +0 -15
  231. package/src/core/validate.ts +0 -348
  232. package/src/presets/index.ts +0 -579
  233. /package/dist/types/{adapters/devices → platforms}/fortios/models.d.ts +0 -0
  234. /package/dist/types/{adapters/devices → platforms}/junos/models.d.ts +0 -0
  235. /package/dist/types/{adapters/devices → platforms}/raisecom-ros/models.d.ts +0 -0
  236. /package/dist/types/{adapters/devices → platforms}/vrp/models.d.ts +0 -0
  237. /package/src/{adapters/devices → platforms}/fortios/models.ts +0 -0
  238. /package/src/{adapters/devices → platforms}/junos/models.ts +0 -0
  239. /package/src/{adapters/devices → platforms}/raisecom-ros/models.ts +0 -0
  240. /package/src/{adapters/devices → platforms}/vrp/models.ts +0 -0
@@ -0,0 +1,52 @@
1
+ import type { Device, Family } from "../../schema";
2
+ type Addressed = {
3
+ addresses?: readonly (string | {
4
+ address: string;
5
+ peer?: string;
6
+ })[];
7
+ vrf?: string;
8
+ lag?: string;
9
+ };
10
+ export declare class FortiOsNames {
11
+ /** The bridges a device has, in the config's order. A device with any runs in transparent mode, each bridge a forward domain numbered by its place. */
12
+ static bridgesOf(device: Device): {
13
+ name: string;
14
+ members: readonly string[];
15
+ }[];
16
+ /** Whether the device runs in transparent mode: it has a bridge. */
17
+ static isTransparent(device: Device): boolean;
18
+ /**
19
+ * The management address of a device in transparent mode: the one IPv4 address on a port or an interface outside every bridge. The device answers on it, the platform's `manageip`, through that interface alone. Undefined when there is none, and the device is reached only through its console.
20
+ */
21
+ static transparentManagement(device: Device): {
22
+ name: string;
23
+ address: string;
24
+ } | undefined;
25
+ /** The forward domain of a VLAN interface in a bridge, or undefined. */
26
+ static forwardDomainOf(device: Device, name: string): number | undefined;
27
+ /** The name the platform gives a port or an interface: a port by its spelling, any other interface by its key. */
28
+ static nameOf(device: Device, name: string): string;
29
+ /** A port's or an interface's settings, by its key. */
30
+ static settingsOf(device: Device, name: string): Addressed | undefined;
31
+ /** Every address of a port or an interface. */
32
+ static addressesOf(settings: Addressed | undefined): string[];
33
+ /** An address or prefix with its length, a bare address taken as a host. */
34
+ static withLength(value: string): string;
35
+ /** The family of an address or prefix. */
36
+ static familyOfPrefix(value: string): Family;
37
+ /** `192.0.2.0 255.255.255.0`, how the platform writes an IPv4 prefix. */
38
+ static subnet(prefix: string): string;
39
+ /** The canonical form of a prefix: its network address and length, a bare address taken as a host. */
40
+ static network(prefix: string): string;
41
+ /** The number of a VRF on the platform: its place among the device's VRFs, the default table being 0. */
42
+ static vrfNumber(device: Device, vrf: string | undefined): number;
43
+ /** Every port and interface that routes, by key, with its settings. A LAG member routes through its LAG. */
44
+ private static routedHolders;
45
+ /** The interface whose own network holds an address, the most specific when several do, in one routing table. */
46
+ static interfaceFor(device: Device, address: string, vrf?: string): string | undefined;
47
+ /** The interface that holds an address as its own. */
48
+ static holderOf(device: Device, address: string): string | undefined;
49
+ /** Every port and interface with an address, by key, where the device's services answer. */
50
+ static addressed(device: Device): string[];
51
+ }
52
+ export {};
@@ -0,0 +1,104 @@
1
+ import type { ApplyOptions, Plan } from "../platform";
2
+ export declare class FortiOsPlan {
3
+ /** Objects every FortiGate running 6.2 is shipped with, which policies and profiles of the factory name. */
4
+ private static readonly FACTORY_ADDRESSES;
5
+ private static readonly FACTORY_SERVICES;
6
+ /** The device's own certificates, which the factory makes for each device. */
7
+ private static readonly FACTORY_CERTIFICATES;
8
+ private static readonly ORDERED;
9
+ /** Tables whose entries need more than a plain comparison, by section. */
10
+ private static readonly TABLES;
11
+ /** Settings the device keeps for itself: an object's UUID and an interface's SNMP index. */
12
+ private static readonly IGNORED;
13
+ /** Settings of one section the device keeps for itself: how changes are saved, which `apply` sets while it works, and the alias it gives itself at every start. */
14
+ private static readonly IGNORED_IN;
15
+ /** In a certificate's entry, the settings that matter: its text and its key. The device prints others it decides for itself. */
16
+ private static readonly KEPT;
17
+ /** A policy denies unless told otherwise. */
18
+ private static readonly DENY;
19
+ /** Defaults the device does not print, by section. A config may state one, such as SSH on port 22, and the render states some because other settings appear only once they hold: a DHCP server's resolvers show only while it names them itself, and a policy answers a denied sender only while it denies. */
20
+ private static readonly DEFAULTS;
21
+ /** Settings whose value is a secret wherever they appear, such as a certificate's key, which the device prints encrypted. */
22
+ private static readonly SECRET_KEYS;
23
+ /** Settings holding a certificate's text, compared without its line breaks. */
24
+ private static readonly CERTIFICATES;
25
+ /** Settings undone before a nested list is deleted. Any other goes after it. */
26
+ private static readonly FIRST;
27
+ /** Settings holding a list in no particular order. */
28
+ private static readonly LISTS;
29
+ /** Settings that name an interface: an entry's own, or a list a section holds, such as OSPF's passive interfaces or the interfaces NTP answers on. */
30
+ private static readonly NAMES_INTERFACE;
31
+ /** Tables whose entries are named after an interface, so that releasing the interface deletes its entry: `The vxlan device is currently used` otherwise. */
32
+ private static readonly KEYED_BY_INTERFACE;
33
+ /** The tables whose entries are interfaces, so that releasing one frees what names it. */
34
+ private static readonly INTERFACE_TABLES;
35
+ /**
36
+ * Lists of interfaces that exist only while a setting is on, by the list. NTP serves only on interfaces it names, so its list cannot be emptied while it serves, `There aren't any interfaces with NTP server enabled`; turning it off hides the list and lets go of them.
37
+ */
38
+ private static readonly HELD_BY;
39
+ /** The interfaces of tunnels, which their own tables create, compared after those tables as a section of their own. */
40
+ private static readonly TUNNELS;
41
+ /** A value that is a secret: a marker in the render, a cipher or a redaction in the read. */
42
+ private static isSecret;
43
+ /** A value in the form both sides compare in: words without quotes, a secret as one word, a list sorted. */
44
+ private static canonical;
45
+ /** Whether an entry changes a setting it keeps for life, so it must be created again. */
46
+ private static changesFixed;
47
+ /** Whether the device holds an entry the plan leaves alone. */
48
+ private static isFactory;
49
+ /** The configuration as the plan reads it: factory entries and the device's own settings left out. */
50
+ static clean(text: string): string;
51
+ private static dropIgnored;
52
+ /** The words before a line a reviewer reads, naming the entry and block it sits in. */
53
+ private static labelOf;
54
+ /** A block's lines as reviewer lines, each with its place. An entry that holds nothing, such as an extra IPv6 address, is its own line. */
55
+ private static shown;
56
+ /** The lines that create an entry, with the settings the device adds unset when the render does not hold them. */
57
+ private static creation;
58
+ /**
59
+ * Compare one block. `table` applies to its entries; `top` sends their removal to the end of the plan.
60
+ *
61
+ * What goes is undone before what comes is set, since a setting can hide another: `send-deny-packet` exists only while a policy denies. A nested list that goes is deleted before the settings, since one can hide the list and keep its entries hidden, such as `secondary-IP`; NTP refuses to delete its last server while it synchronises, so `ntpsync` goes before its list.
62
+ */
63
+ private static compare;
64
+ /** Entries matched by name: new ones created, changed ones edited, gone ones deleted, and an ordered table put in order. */
65
+ private static byId;
66
+ /** Entries matched by name in a table that refuses two alike: every entry that changes or goes is deleted before any is created, so none is ever briefly the same as another. */
67
+ private static distinctById;
68
+ /** The `move` commands that put a table's entries in the render's order. Kept entries hold their place on the device and new ones are added at the end. */
69
+ private static moves;
70
+ /** An entry's settings in the form two entries compare in, whatever their numbers. */
71
+ private static signature;
72
+ /** Entries matched by what they hold. One the device holds and the render does not is deleted; one the render adds takes a number the device does not use. */
73
+ private static byContent;
74
+ /** The interface names a block's settings hold. */
75
+ private static interfacesNamed;
76
+ /**
77
+ * What goes before anything else changes.
78
+ *
79
+ * A port joins a LAG only while nothing names it, and its speed cannot change while it is in one. So a LAG that keeps some of its ports lets the others go first, a port whose speed changes leaves its LAG and joins again later, a LAG whose ports join another goes first, and an interface whose type or parent changes is deleted and created again. Whatever names such an interface on the device is deleted first, or unset when a list names it, and set again later if the render holds it; an interface or tunnel deleted this way frees what names it in turn.
80
+ *
81
+ * A LAG that goes otherwise is deleted with everything else that goes, after what names it; its ports are changed after that.
82
+ */
83
+ private static released;
84
+ /**
85
+ * The lines, inside one block, that release what names a freed interface: an entry that names one is deleted, and a list a block holds that names one is unset. The device's tree loses them too, so the plan creates or sets them again. An interface the release deletes itself is in `gone`.
86
+ */
87
+ private static release;
88
+ /**
89
+ * Addresses that leave an interface, taken off before any is set: the device refuses an address in a subnet another interface still holds, `Subnets overlap`. A primary address that changes takes the secondary ones with it, since they hang on it.
90
+ */
91
+ private static movedAddresses;
92
+ /**
93
+ * What changes, by section, in the order the render lists them. Entries that go are deleted after everything else, in the reverse order, so nothing is deleted while another section still names it.
94
+ *
95
+ * A secret is sent when its entry is new, or with `secrets` set; it cannot be read back to compare.
96
+ */
97
+ static of(desired: string, current: string, options: Pick<ApplyOptions, "secrets">): Plan;
98
+ /** The tree with each tunnel's interface moved from `system interface` to a section of its own, just after the tunnels' tables. The interface it leaves through is its tunnel's, and is left to the tunnel's table. */
99
+ private static separateTunnels;
100
+ /** A prefix list `refresh` fills keeps the entries the device holds. */
101
+ private static keepFilled;
102
+ /** The ports of a LAG that goes, taken out of the main comparison and changed in a step of their own once the LAG is deleted. */
103
+ private static deferredPorts;
104
+ }
@@ -0,0 +1,75 @@
1
+ import type { Device, Helper, Severity } from "../../schema";
2
+ export type Section = (typeof FortiOsRender.SECTIONS)[number];
3
+ export declare class FortiOsRender {
4
+ /** Where the pre-login banner's text is kept. */
5
+ static readonly BANNER = "system replacemsg admin \"pre_admin-disclaimer-text\"";
6
+ /** Every section Circuit manages, in the order a change goes in: what others name comes first. */
7
+ static readonly SECTIONS: readonly ["vpn certificate local", "vpn certificate ca", "system global", "system replacemsg admin \"pre_admin-disclaimer-text\"", "system settings", "system accprofile", "system admin", "system interface", "system gre-tunnel", "system vxlan", "system dns", "system dns-server", "system ntp", "system snmp sysinfo", "system snmp community", "system snmp user", "log memory setting", "log memory filter", "log disk setting", ...string[], "system sflow", "system netflow", "system dhcp server", "router static", "router static6", "router prefix-list", "router prefix-list6", "router community-list", "router route-map", "router ospf", "router ospf6", "router bgp", "system session-helper", "firewall address", "firewall address6", "firewall addrgrp", "firewall addrgrp6", "firewall service custom", "firewall ippool", "firewall vip", "firewall policy", "firewall policy6", "firewall local-in-policy", "firewall local-in-policy6", "firewall central-snat-map", "firewall acl", "firewall acl6"];
8
+ /** Sections `show` prints without what matters, which `show full-configuration` prints: a certificate's text. */
9
+ static readonly FULL: readonly string[];
10
+ /** The FortiOS zone number of each IANA zone it has one for. A number names a list of places in one zone; `00` is the device's default. */
11
+ private static readonly ZONES;
12
+ /** What each role may do: the factory profile for an admin, and a profile Circuit adds for the others. */
13
+ static readonly PROFILE: {
14
+ readonly admin: "super_admin";
15
+ readonly operator: "circuit-operator";
16
+ readonly "read-only": "circuit-read-only";
17
+ };
18
+ /** The permission groups of an access profile. */
19
+ private static readonly PERMISSION_GROUPS;
20
+ /** The most public keys a user holds. */
21
+ static readonly SSH_KEYS = 3;
22
+ /** The most resolvers the device and a DHCP server hold, per family. */
23
+ static readonly RESOLVERS: {
24
+ readonly device: 2;
25
+ readonly dhcp: 4;
26
+ };
27
+ /** The most syslog collectors the device sends to. */
28
+ static readonly COLLECTORS = 4;
29
+ /** The most VRFs the device holds besides its default table. */
30
+ static readonly VRFS = 31;
31
+ /** A severity as the platform names it. */
32
+ static readonly LEVEL: Record<Severity, string>;
33
+ /** The helpers the factory runs, by the name a config gives them: protocol and port of each. */
34
+ static readonly HELPERS: Partial<Record<Helper, readonly [string, number, number][]>>;
35
+ /** Speed by the platform's spelling, for each class a port's cage takes. */
36
+ static readonly SPEEDS: Record<string, Partial<Record<string, string>>>;
37
+ /** The management address of a device in transparent mode, which is reached only through its console: link-local, on no network it can reach. */
38
+ static readonly TRANSPARENT_MANAGEIP = "169.254.0.1/255.255.255.255";
39
+ /** The zone number for an IANA zone. UTC when the config names none. */
40
+ static zoneOf(timezone?: string): string | undefined;
41
+ /** The services a port or an interface answers on its addresses: ping always, and every management service the config turns on. */
42
+ private static allowAccess;
43
+ /** The whole configuration the device should run, in the form `show` prints. */
44
+ static of(device: Device): string;
45
+ /** A certificate with its key is the device's own; one without is only trusted. */
46
+ private static certificates;
47
+ private static global;
48
+ /** Each user, with the profile its role takes. */
49
+ private static users;
50
+ /** Ports, then the LAGs they join, VLAN interfaces on them, loopbacks, and the tunnels with their own tables. */
51
+ private static interfaces;
52
+ /** The platform sends ICMP redirects unless an interface says otherwise; the config sends them only when asked. */
53
+ private static redirects;
54
+ /** The one port or LAG that carries a VLAN tagged, which its VLAN interface sits on. `unsupported()` refuses any other case. */
55
+ static vlanParent(device: Device, vlan: string): string | undefined;
56
+ /** Addresses and their routing table, the services answered on them, VRRP, DHCP relay, router advertisements, LLDP and flow sampling of a port or an interface. */
57
+ private static routed;
58
+ /** The device's resolvers, and the interfaces it answers DNS queries on when it serves them. */
59
+ private static dns;
60
+ /** The servers the device keeps time from, and the interfaces it answers time queries on when it serves them. */
61
+ private static ntp;
62
+ /** SNMP version 2c with one community, guarded by its hosts, and version 3 users. */
63
+ private static snmp;
64
+ /** Logs kept in memory from a level up, none on disk, and up to four syslog collectors, each with the least severe message it takes. */
65
+ private static logging;
66
+ /** One collector, and sampling on each interface it observes. */
67
+ private static flowExport;
68
+ private static dhcpServers;
69
+ /** Each route by its position. A route goes in the routing table of the interface it leaves through. A default route is the platform's default destination and is not printed. */
70
+ private static staticRoutes;
71
+ /** BFD runs once a route or a session uses it, or the config sets its timers, which the device shows only while it runs. */
72
+ private static bfd;
73
+ /** The helpers the config lists, each on the protocols and ports the factory gives it. None run otherwise. */
74
+ private static helpers;
75
+ }
@@ -0,0 +1,56 @@
1
+ import type { Device, Family, Neighbor, NeighborSettings, PolicyRule } from "../../schema";
2
+ import { FortiOsBlock } from "./tree";
3
+ type AnyRule = PolicyRule<string, string>;
4
+ type AnyNeighbor = Neighbor<string, string>;
5
+ /** The lengths a prefix list's rule takes within its prefix. */
6
+ type Lengths = {
7
+ ge?: number;
8
+ le?: number;
9
+ };
10
+ export declare class FortiOsRouting {
11
+ /** The route map a session takes when its config states none, so it learns or announces nothing. */
12
+ static readonly REJECT_ALL = "circuit-reject-all";
13
+ /** The start of the comment on a prefix list `refresh` fills. The plan keeps the entries the device holds in one. */
14
+ static readonly FILLED = "Filled by circuit refresh";
15
+ /** The table a prefix list of one family sits in. */
16
+ static readonly PREFIX_LIST: {
17
+ readonly ipv4: "router prefix-list";
18
+ readonly ipv6: "router prefix-list6";
19
+ };
20
+ /** The longest prefix of each family. */
21
+ static readonly BITS: {
22
+ readonly ipv4: 32;
23
+ readonly ipv6: 128;
24
+ };
25
+ /** A neighbor's settings with its group's beneath them. */
26
+ static neighborSettings(device: Device, neighbor: AnyNeighbor): NeighborSettings<string>;
27
+ /** The families a session carries: its own, or the family of its address. */
28
+ static familiesOfNeighbor(device: Device, neighbor: AnyNeighbor): Family[];
29
+ /** Whether a static route, OSPF or BGP detects a dead neighbor with BFD, which the device then runs. */
30
+ static usesBfd(device: Device): boolean;
31
+ static render(root: FortiOsBlock, device: Device): void;
32
+ /** A prefix as the platform writes it in a prefix list of its family. */
33
+ private static listPrefix;
34
+ /** One rule of a prefix list: a prefix, and the lengths it takes within it. The device prints a bound the rule does not hold as `unset`. */
35
+ static listRule(rule: FortiOsBlock, family: Family, prefix: string, lengths?: Lengths): void;
36
+ /** The lengths a rule takes within a prefix to match lengths from `min` to `max`, or none when no length fits. A bound equal to the prefix's own length is left out. */
37
+ static bounds(prefix: string, family: Family, min?: number, max?: number): Lengths | undefined;
38
+ /** Each prefix set as a prefix list matching its prefixes and any more specific. One a registry fills starts with a rule that denies every prefix, so it matches nothing until `refresh` fills it. */
39
+ private static prefixLists;
40
+ /** The networks of an interface's addresses of one family, for an OSPF area to announce. */
41
+ private static networksOf;
42
+ /** OSPF for IPv4. An area runs on the networks of its interfaces; an interface named with a cost, a link type or BFD has settings of its own; a passive one forms no adjacency. */
43
+ private static ospf;
44
+ /** OSPFv3 for IPv6. Every interface of an area runs it in that area. */
45
+ private static ospf6;
46
+ /** BGP: each session with its settings and group's, the route maps its policies become for each family it carries, and the prefixes the device originates. */
47
+ private static bgp;
48
+ /** The family a rule is limited to, by its match: a family, a prefix, or a prefix set of one family. */
49
+ static familyOfRule(device: Device, rule: AnyRule): Family | undefined;
50
+ /** A policy's rules with each call replaced by the rules it calls, in order. A called policy that decides nothing hands back to the caller. */
51
+ static flatten(device: Device, policy: string, seen?: string[]): AnyRule[];
52
+ /** Routing the platform cannot express, or that this adapter does not yet write. */
53
+ static gaps(device: Device): string[];
54
+ private static ruleGaps;
55
+ }
56
+ export {};
@@ -0,0 +1,37 @@
1
+ /** One `edit` of a table: its name as written, and what it holds. */
2
+ export type Entry = {
3
+ id: string;
4
+ block: FortiOsBlock;
5
+ };
6
+ export declare class FortiOsBlock {
7
+ readonly settings: Map<string, string>;
8
+ readonly blocks: Map<string, FortiOsBlock>;
9
+ readonly entries: Map<string, Entry>;
10
+ /** Set a key. A value of several words is written as given. */
11
+ set(key: string, value: string | number): this;
12
+ /** The nested `config` block with this header, created when absent. */
13
+ block(header: string): FortiOsBlock;
14
+ /** The table entry with this name, created when absent. A name is quoted unless it is a number, or the table prints it bare, such as an OSPF area or an IPv6 prefix. */
15
+ entry(id: string | number, plain?: boolean): FortiOsBlock;
16
+ isEmpty(): boolean;
17
+ }
18
+ export declare class FortiOsTree {
19
+ /** A setting the device prints as `unset <key>`, a key it holds empty on purpose, such as an ICMP service's type. */
20
+ static readonly UNSET = "\0unset";
21
+ /** A string as the CLI takes it, in double quotes. */
22
+ static quote(text: string): string;
23
+ /** Each of several strings quoted, as a list setting takes them. */
24
+ static quoteAll(texts: readonly string[]): string;
25
+ /** A value's words; a quoted string is one word with its quotes. */
26
+ static words(value: string): string[];
27
+ /** A word as the device means it, without quotes or escapes. */
28
+ static bare(word: string): string;
29
+ /** The lines that build a block, at an indent, in the form `show` prints and the CLI takes. */
30
+ static lines(block: FortiOsBlock, indent?: string): string[];
31
+ /** The whole configuration: each top-level block as `config <section>` to `end`. */
32
+ static print(root: FortiOsBlock): string;
33
+ /** Whether a line opens a quoted value it does not close, so the value goes on over the next lines. */
34
+ private static unclosed;
35
+ /** The tree of what `show` printed. Lines that are not configuration, such as the version header, are skipped. */
36
+ static parse(text: string): FortiOsBlock;
37
+ }
@@ -0,0 +1,13 @@
1
+ import type { Platform } from "./platform";
2
+ /** Every platform the framework can render and apply, by name. */
3
+ export declare class Platforms {
4
+ private static readonly BY_NAME;
5
+ /** The platform of that name, or undefined when there is none. */
6
+ static find(name: string): Platform | undefined;
7
+ /** The platform of that name. Throws when there is none. */
8
+ static get(name: string): Platform;
9
+ /** Every platform, in the order the framework lists them. */
10
+ static all(): Platform[];
11
+ /** Every platform's name. */
12
+ static names(): string[];
13
+ }
@@ -0,0 +1,44 @@
1
+ import type { Device, Neighbor, NeighborSettings } from "../../schema";
2
+ import { type JunosStatements } from "./render";
3
+ type AnyNeighbor = Neighbor<string, string>;
4
+ /** BGP sessions, the policies they use, prefix sets and RPKI servers, added to one device's statements. */
5
+ export declare class JunosBgp {
6
+ private readonly out;
7
+ private readonly device;
8
+ /** The policy a session uses when it states none, so that it learns or announces nothing. */
9
+ private static readonly REJECT_ALL;
10
+ /** The policy every export starts with. BGP's own routes and the prefixes the device originates go on to the session's policy; the device's other routes never reach it. */
11
+ private static readonly ORIGIN;
12
+ /** The validator group every RPKI server joins. */
13
+ private static readonly RPKI_GROUP;
14
+ /** A comment in the render naming a path whose statements `refresh` fills, so the plan keeps what the device holds there. */
15
+ static readonly GENERATED = "# generated ";
16
+ private static readonly FAMILY;
17
+ private static readonly VALIDATION;
18
+ private constructor();
19
+ /** Add the device's prefix sets, RPKI servers, BGP sessions and the policies they use. */
20
+ static render(out: JunosStatements, device: Device): void;
21
+ /** A neighbor's settings with its group's beneath them. */
22
+ static settingsOf(device: Device, neighbor: AnyNeighbor): NeighborSettings<string>;
23
+ /** A name made of a value's words, for a community or a path-length list: `64500:*` becomes `64500-any`. */
24
+ private static slug;
25
+ /** A community as the platform writes a member: a large community carries the `large:` prefix. */
26
+ private static member;
27
+ /** A term's name: its place, then the rule's description so a reader sees it on the device. */
28
+ private static termName;
29
+ private sessions;
30
+ /** BGP's routes and the originated prefixes go on to the session's policy; anything else is rejected. */
31
+ private origin;
32
+ private prefixSets;
33
+ private rpki;
34
+ /** The family a rule is limited to, by its match: a family, a prefix, or a prefix set of one family. */
35
+ private familyOfRule;
36
+ /** A policy's rules with each call replaced by the rules it calls, in order. A called policy that decides nothing hands back to the caller, as it does on every platform. */
37
+ private flatten;
38
+ /** One policy as a policy statement: a term per rule, then a reject when the last rule does not decide on every route. */
39
+ private policyStatement;
40
+ private term;
41
+ /** A named community holding these members, named after them. */
42
+ private community;
43
+ }
44
+ export {};
@@ -0,0 +1,114 @@
1
+ import type { Neighbor } from "../../core/cabling";
2
+ import type { Device, Family } from "../../schema";
3
+ import { type ConsoleDialect } from "../../transport/console";
4
+ import { type ApplyOptions, type OsSupport, type Plan, type ReadOptions, type ReadSession, Platform } from "../platform";
5
+ /** How a commit that could cut access is guarded: it rolls back after `minutes` unless `prove` shows access survived. */
6
+ export type Guard = {
7
+ minutes: number;
8
+ prove: () => Promise<void>;
9
+ };
10
+ export declare class Junos extends Platform {
11
+ /** How the console asks for a login. Root lands in a shell, `%`, every other user in the CLI, `>`; a session left in configuration mode, `#`, leaves it first. Not yet proved on a device. */
12
+ static readonly CONSOLE: ConsoleDialect;
13
+ /** The release this adapter renders for, and was proved on. */
14
+ private static readonly SUPPORTED_MAJOR;
15
+ /** Statements the device keeps for itself: the release it runs and the number it gives each user. */
16
+ private static readonly DEVICE_FACTS;
17
+ /** Names the platform keeps for its own system accounts. A user under one fails the commit check. */
18
+ private static readonly SYSTEM_ACCOUNTS;
19
+ /** A value the device keeps hashed or encrypted, and the render writes as a marker, as one word both sides share. Each keeps the number of words. */
20
+ private static readonly SECRETS;
21
+ /** Lists whose entries are named: a delete cannot stop at the list, `delete interfaces xe-0/0/1 unit`, only at an entry, `unit 0`. A leaf-list such as `vlan members` or `ciphers` can go whole. */
22
+ private static readonly NAMED_LISTS;
23
+ /** A prompt at the end of what the device printed: `user@host> `, `user@host# `, or a shell's `% `. */
24
+ private static readonly PROMPT;
25
+ /** The prompt in configuration mode, under its `[edit]` line. An echoed statement cannot end with it. */
26
+ private static readonly EDIT_PROMPT;
27
+ /** What the device says when it refuses a statement in a load: `terminal:3:(14) syntax error: ...`. A warning, such as a statement not found, is not a refusal. */
28
+ private static readonly REFUSED;
29
+ /** Every LLDP neighbor with the far port, which the brief form leaves out. */
30
+ private static readonly LLDP_NEIGHBORS;
31
+ /** Commands that only read. */
32
+ private static readonly READS;
33
+ /** Features `Derive.unproved` refuses until a platform proves them, proved here on a QFX5100-48S-6Q running Junos 21.4R3. */
34
+ private static readonly PROVED;
35
+ readonly name = "junos";
36
+ readonly os: OsSupport;
37
+ readonly extension = ".conf";
38
+ readonly console: ConsoleDialect;
39
+ unsupported(device: Device): string[];
40
+ render(device: Device): string;
41
+ read(device: Device, _network?: readonly Device[], options?: ReadOptions): Promise<string>;
42
+ /** The LLDP neighbors from `show lldp neighbors detail` as XML. The brief form leaves out the far port, and its table pads columns that a description can fill. */
43
+ neighbors(device: Device, _network?: readonly Device[], options?: ReadOptions): Promise<Neighbor[]>;
44
+ /** Each neighbor in the XML the device printed, on our port by Circuit's name. The far end's system name, or its chassis ID when it sends none. */
45
+ static neighborsOf(device: Device, xml: string): Neighbor[];
46
+ private static unescapeXml;
47
+ /**
48
+ * What changes, by section.
49
+ *
50
+ * A statement the render holds and the device does not is set. One the device holds and the render does not is deleted at the shortest path that holds nothing the render wants, so a removed port goes as a whole and a changed value goes alone. A hidden value ends a path by its name alone; a hidden name in a list, such as a community, stays `<redacted>` and the session names each entry when it sends the plan. A statement the device holds deactivated is activated when the render wants it.
51
+ *
52
+ * A policy, a filter or an import or export chain is ordered, so when anything in one changes it is deleted and set again whole, in the render's order. A path the render marks as generated, such as a prefix list `refresh` fills, keeps what the device holds.
53
+ */
54
+ plan(desired: string, current: string, options: Pick<ApplyOptions, "secrets">): Plan;
55
+ apply(device: Device, _network: readonly Device[], plan: Plan, options: ApplyOptions): Promise<void>;
56
+ /** Replace a prefix list `refresh` fetched. It cannot cut access, so it is committed without a rollback. */
57
+ fill(device: Device, _network: readonly Device[], set: string, _family: Family, prefixes: string[]): Promise<void>;
58
+ readOnly(command: string): boolean;
59
+ /** Over SSH, each command runs on its own, as the read does. */
60
+ session(device: Device, options?: ReadOptions): Promise<ReadSession>;
61
+ /** A statement's words; a quoted value is one word with its quotes. */
62
+ private static wordsOf;
63
+ /** A word as the platform means it, without quotes or escapes, so a value quoted on one side and not on the other compares equal. */
64
+ private static bare;
65
+ /** A statement in the form both sides compare in: its words, secrets as one marker, quotes dropped. */
66
+ private static keyOf;
67
+ /** The device prints a password as a hash, an SNMP key as a reversible cipher, and a community as itself. None leave the read. */
68
+ private static scrub;
69
+ /** The configuration's statements from what `show configuration | display set` printed. */
70
+ private static clean;
71
+ /** Whether a delete may stop after `path[index]`. Below the top level a named list may not; `vlan` names a list except in `vlan members`. */
72
+ private static canStopAt;
73
+ /** The section a statement belongs to, for a reviewer: `interfaces xe-0/0/1`, `system login`, `snmp`. */
74
+ private static sectionOf;
75
+ /**
76
+ * The ordered block a statement sits in, and its item there: a policy's or a filter's term, or one policy of an import or export chain. The device keeps their order, and `set` adds at the end.
77
+ */
78
+ private static orderedBlockOf;
79
+ /** Whether a path starts with another. */
80
+ private static startsWith;
81
+ private static login;
82
+ /** Refuse a device on a release this adapter was not proved on, before anything is read or sent. */
83
+ private static checkVersion;
84
+ /** Send one line and wait for the prompt to come back. */
85
+ private static run;
86
+ /** Send one line in configuration mode and wait for its prompt to come back. */
87
+ private static edit;
88
+ /** Log in on the console and open the CLI. Returns the console, a way to log in afresh, and how to let the console go. */
89
+ private static openConsole;
90
+ /** Log in on the console, open the CLI, and run `work` in it with a way to log in afresh. Logs out after. */
91
+ private static onConsole;
92
+ /** An interactive CLI with paging off. Root lands in a shell and starts the CLI from there. */
93
+ private static openCli;
94
+ /**
95
+ * A delete through a name the read redacted, `delete snmp community <redacted>`, as one delete for each entry the device holds there. The names stay in the session.
96
+ */
97
+ private static named;
98
+ /**
99
+ * Load the plan into an exclusive candidate and check it. With a guard, commit it to roll back after `minutes`, prove access, then confirm; without one, commit it outright.
100
+ *
101
+ * Deletions go before the statements that are set, so a path deleted and set again in one plan ends up set.
102
+ */
103
+ private static configure;
104
+ /** The plan that replaces a prefix list's entries with what a registry returned. */
105
+ private static fillPlan;
106
+ /** The IP MTU of every port and LAG that carries a VLAN; 1500 where none is given. */
107
+ private static carriers;
108
+ /** BGP settings Junos 21 has no statement for, and policy steps it cannot take. */
109
+ private static bgpGaps;
110
+ /** Layer 3 settings the platform cannot express on a port or an interface. */
111
+ private static routedGaps;
112
+ /** Storm control in a form a profile holds: one threshold in percent for every kind. */
113
+ private static switchedGaps;
114
+ }