@takodotid/circuit 0.43.1 → 1.0.0-rc.2
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 +115 -37
- package/package.json +21 -58
- package/src/checks/across.ts +402 -0
- package/src/checks/built-in.ts +256 -0
- package/src/checks/device.ts +436 -0
- package/src/checks/index.ts +53 -0
- package/src/cli/advisories.ts +108 -0
- package/src/cli/app.ts +71 -0
- package/src/cli/editor-types.generated.ts +30 -0
- package/src/cli/editor-types.ts +69 -0
- package/src/cli/format.ts +124 -0
- package/src/cli/git-hooks.ts +79 -0
- package/src/cli/index.ts +350 -1170
- package/src/cli/migrate.ts +554 -0
- package/src/cli/project-commands.ts +656 -0
- package/src/cli/releases.ts +374 -0
- package/src/cli/remember.ts +339 -0
- package/src/cli/rename.ts +27 -33
- package/src/cli/secrets-password.ts +60 -0
- package/src/cli/secrets.ts +258 -0
- package/src/cli/setup.ts +300 -0
- package/src/cli/signing.ts +23 -0
- package/src/cli/text-editor.ts +268 -0
- package/src/cli/ui.ts +298 -0
- package/src/cli/version.ts +2 -0
- package/src/cli/versions.ts +158 -0
- package/src/config/address.ts +102 -0
- package/src/config/circuit.d.ts +30 -0
- package/src/config/common.ts +65 -0
- package/src/config/communities.ts +479 -0
- package/src/config/define.ts +684 -0
- package/src/config/device.ts +164 -0
- package/src/config/firewall.ts +150 -0
- package/src/config/index.ts +22 -0
- package/src/{schema → config}/interfaces.ts +121 -85
- package/src/config/keys.ts +434 -0
- package/src/config/management.ts +61 -0
- package/src/config/merge.ts +335 -0
- package/src/config/models.ts +70 -0
- package/src/config/monitoring.ts +64 -0
- package/src/config/network.ts +180 -0
- package/src/config/presets.ts +149 -0
- package/src/config/routing.ts +401 -0
- package/src/config/services.ts +51 -0
- package/src/config/switching.ts +84 -0
- package/src/config/system.ts +103 -0
- package/src/{schema → config}/time-zones.ts +1 -1
- package/src/core/address.ts +1 -1
- package/src/core/cabling.ts +8 -43
- package/src/core/graph.ts +40 -0
- package/src/{integrations → core}/registries.ts +5 -3
- package/src/core/secrets-file.ts +539 -0
- package/src/core/secrets.ts +83 -64
- package/src/core/topology.ts +103 -146
- package/src/core/utils.ts +12 -1
- package/src/model.ts +83 -0
- package/src/platforms/derive.ts +64 -37
- package/src/platforms/finding.ts +9 -0
- package/src/platforms/fortios/firewall.ts +76 -64
- package/src/platforms/fortios/index.ts +189 -125
- package/src/platforms/fortios/names.ts +51 -18
- package/src/platforms/fortios/render.ts +69 -62
- package/src/platforms/fortios/routing.ts +89 -58
- package/src/platforms/fortios/vdoms.ts +47 -16
- package/src/platforms/junos/TRAPS.md +2 -2
- package/src/platforms/junos/bgp.ts +63 -42
- package/src/platforms/junos/index.ts +122 -89
- package/src/platforms/junos/render.ts +139 -104
- package/src/platforms/platform.ts +10 -8
- package/src/platforms/raisecom-ros/TRAPS.md +1 -1
- package/src/platforms/raisecom-ros/index.ts +89 -70
- package/src/platforms/raisecom-ros/render.ts +49 -45
- package/src/platforms/routeros/TRAPS.md +3 -3
- package/src/platforms/routeros/index.ts +121 -60
- package/src/platforms/routeros/render.ts +214 -195
- package/src/platforms/vrp/TRAPS.md +1 -1
- package/src/platforms/vrp/index.ts +74 -50
- package/src/platforms/vrp/render.ts +67 -56
- package/src/project/project.ts +725 -0
- package/src/studio/app/env.d.ts +9 -0
- package/src/studio/app/index.html +18 -0
- package/src/studio/app/src/App.vue +95 -0
- package/src/studio/app/src/components/AddressesView.vue +38 -0
- package/src/studio/app/src/components/CablesView.vue +29 -0
- package/src/studio/app/src/components/CompareView.vue +160 -0
- package/src/studio/app/src/components/DataTable.vue +49 -0
- package/src/studio/app/src/components/DeviceView.vue +237 -0
- package/src/studio/app/src/components/DevicesView.vue +32 -0
- package/src/studio/app/src/components/Faceplate.vue +75 -0
- package/src/studio/app/src/components/GraphView.vue +282 -0
- package/src/studio/app/src/components/LineDiff.vue +24 -0
- package/src/studio/app/src/components/ProblemsView.vue +42 -0
- package/src/studio/app/src/components/SearchView.vue +72 -0
- package/src/studio/app/src/components/SecretsView.vue +112 -0
- package/src/studio/app/src/components/SessionsView.vue +35 -0
- package/src/studio/app/src/components/Settings.vue +95 -0
- package/src/studio/app/src/components/ToolsView.vue +118 -0
- package/src/studio/app/src/components/VlansView.vue +50 -0
- package/src/studio/app/src/lib/csv.ts +19 -0
- package/src/studio/{public/diff.js → app/src/lib/diff.ts} +40 -35
- package/src/studio/app/src/lib/format.ts +38 -0
- package/src/studio/app/src/lib/net.ts +68 -0
- package/src/studio/app/src/lib/secrets-crypto.ts +35 -0
- package/src/studio/app/src/lib/store.ts +71 -0
- package/src/studio/app/src/lib/tools.ts +217 -0
- package/src/studio/app/src/main.ts +9 -0
- package/src/studio/{public → app/src}/style.css +14 -4
- package/src/studio/app/tsconfig.json +17 -0
- package/src/studio/app/vite.config.ts +16 -0
- package/src/studio/assets.generated.ts +3 -0
- package/src/studio/data.ts +96 -188
- package/src/studio/git.ts +27 -43
- package/src/studio/server.ts +196 -107
- package/src/studio/types.ts +141 -0
- package/src/transport/console.ts +3 -3
- package/src/transport/ssh.ts +1 -1
- package/dist/chunks/index-3b343xva.js +0 -177
- package/dist/chunks/index-6wb41q67.js +0 -62
- package/dist/chunks/index-n7w3tg5y.js +0 -149
- package/dist/chunks/index-yzw86rc8.js +0 -921
- package/dist/chunks/new-w3zys5y4.js +0 -172
- package/dist/chunks/server-cxr9ynxc.js +0 -259
- package/dist/cli/index.js +0 -12922
- package/dist/helpers/index.js +0 -881
- package/dist/index.js +0 -28
- package/dist/types/core/address-space.d.ts +0 -62
- package/dist/types/core/address.d.ts +0 -44
- package/dist/types/core/cabling.d.ts +0 -41
- package/dist/types/core/cross-checks.d.ts +0 -28
- package/dist/types/core/define.d.ts +0 -79
- package/dist/types/core/project-files.d.ts +0 -12
- package/dist/types/core/schema-docs.d.ts +0 -25
- package/dist/types/core/secrets.d.ts +0 -62
- package/dist/types/core/topology.d.ts +0 -96
- package/dist/types/core/utils.d.ts +0 -10
- package/dist/types/core/validator.d.ts +0 -23
- package/dist/types/helpers/bgp.d.ts +0 -195
- package/dist/types/helpers/cables.d.ts +0 -69
- package/dist/types/helpers/checks.d.ts +0 -36
- package/dist/types/helpers/exchange.d.ts +0 -55
- package/dist/types/helpers/filters.d.ts +0 -51
- package/dist/types/helpers/index.d.ts +0 -14
- package/dist/types/helpers/route-server.d.ts +0 -52
- package/dist/types/helpers/upstreams.d.ts +0 -192
- package/dist/types/index.d.ts +0 -10
- package/dist/types/integrations/librenms.d.ts +0 -60
- package/dist/types/integrations/netbox.d.ts +0 -89
- package/dist/types/integrations/peeringdb.d.ts +0 -24
- package/dist/types/integrations/prometheus.d.ts +0 -24
- package/dist/types/integrations/registries.d.ts +0 -8
- package/dist/types/platforms/bgp-wait.d.ts +0 -24
- package/dist/types/platforms/catalog.d.ts +0 -109
- package/dist/types/platforms/derive.d.ts +0 -17
- package/dist/types/platforms/fortios/firewall.d.ts +0 -47
- package/dist/types/platforms/fortios/index.d.ts +0 -140
- package/dist/types/platforms/fortios/models.d.ts +0 -14
- package/dist/types/platforms/fortios/names.d.ts +0 -52
- package/dist/types/platforms/fortios/plan.d.ts +0 -114
- package/dist/types/platforms/fortios/render.d.ts +0 -77
- package/dist/types/platforms/fortios/routing.d.ts +0 -56
- package/dist/types/platforms/fortios/tree.d.ts +0 -37
- package/dist/types/platforms/fortios/vdoms.d.ts +0 -50
- package/dist/types/platforms/index.d.ts +0 -13
- package/dist/types/platforms/junos/bgp.d.ts +0 -44
- package/dist/types/platforms/junos/index.d.ts +0 -114
- package/dist/types/platforms/junos/models.d.ts +0 -14
- package/dist/types/platforms/junos/render.d.ts +0 -154
- package/dist/types/platforms/line-diff.d.ts +0 -67
- package/dist/types/platforms/platform.d.ts +0 -135
- package/dist/types/platforms/raisecom-ros/index.d.ts +0 -71
- package/dist/types/platforms/raisecom-ros/models.d.ts +0 -14
- package/dist/types/platforms/raisecom-ros/render.d.ts +0 -41
- package/dist/types/platforms/routeros/export.d.ts +0 -59
- package/dist/types/platforms/routeros/index.d.ts +0 -116
- package/dist/types/platforms/routeros/models.d.ts +0 -18
- package/dist/types/platforms/routeros/plan.d.ts +0 -58
- package/dist/types/platforms/routeros/render.d.ts +0 -250
- package/dist/types/platforms/vrp/index.d.ts +0 -83
- package/dist/types/platforms/vrp/models.d.ts +0 -12
- package/dist/types/platforms/vrp/render.d.ts +0 -96
- package/dist/types/schema/common.d.ts +0 -30
- package/dist/types/schema/device.d.ts +0 -126
- package/dist/types/schema/firewall.d.ts +0 -131
- package/dist/types/schema/index.d.ts +0 -8
- package/dist/types/schema/interfaces.d.ts +0 -205
- package/dist/types/schema/policy.d.ts +0 -107
- package/dist/types/schema/routing.d.ts +0 -161
- package/dist/types/schema/system.d.ts +0 -198
- package/dist/types/schema/time-zones.d.ts +0 -2
- package/dist/types/transport/console.d.ts +0 -115
- package/dist/types/transport/path-check.d.ts +0 -32
- package/dist/types/transport/ssh.d.ts +0 -27
- package/src/cli/graph-format.ts +0 -91
- package/src/cli/new.ts +0 -234
- package/src/core/address-space.ts +0 -320
- package/src/core/cross-checks.ts +0 -369
- package/src/core/define.ts +0 -124
- package/src/core/project-files.ts +0 -35
- package/src/core/schema-docs.ts +0 -174
- package/src/core/validator.ts +0 -508
- package/src/helpers/bgp.ts +0 -473
- package/src/helpers/cables.ts +0 -74
- package/src/helpers/checks.ts +0 -201
- package/src/helpers/exchange.ts +0 -123
- package/src/helpers/filters.ts +0 -107
- package/src/helpers/index.ts +0 -25
- package/src/helpers/route-server.ts +0 -212
- package/src/helpers/upstreams.ts +0 -369
- package/src/index.ts +0 -13
- package/src/integrations/librenms.ts +0 -291
- package/src/integrations/netbox.ts +0 -620
- package/src/integrations/peeringdb.ts +0 -173
- package/src/integrations/prometheus.ts +0 -90
- package/src/schema/common.ts +0 -41
- package/src/schema/device.ts +0 -145
- package/src/schema/firewall.ts +0 -140
- package/src/schema/index.ts +0 -8
- package/src/schema/policy.ts +0 -115
- package/src/schema/routing.ts +0 -173
- package/src/schema/system.ts +0 -203
- package/src/studio/public/app.js +0 -186
- package/src/studio/public/compare.js +0 -250
- package/src/studio/public/dom.js +0 -138
- package/src/studio/public/evaluate.js +0 -687
- package/src/studio/public/export.js +0 -130
- package/src/studio/public/graph.js +0 -1541
- package/src/studio/public/index.html +0 -83
- package/src/studio/public/net.js +0 -134
- package/src/studio/public/tables.js +0 -1289
- package/src/studio/public/tools.js +0 -610
- package/templates/colocation/checks.ts +0 -53
- package/templates/colocation/circuit.config.ts +0 -9
- package/templates/colocation/edge-01.ts +0 -133
- package/templates/colocation/routing.ts +0 -13
- package/templates/colocation/tenancy.ts +0 -76
- package/templates/colocation/tenants/acme.ts +0 -19
- package/templates/colocation/tenants/index.ts +0 -6
- package/templates/colocation/tor-01.ts +0 -33
- package/templates/edge-router/checks.ts +0 -20
- package/templates/edge-router/circuit.config.ts +0 -8
- package/templates/edge-router/edge-01.ts +0 -110
- package/templates/edge-router/routing.ts +0 -13
- package/templates/project/AGENTS.md +0 -51
- package/templates/project/CLAUDE.md +0 -1
- package/templates/project/README.md +0 -16
- package/templates/project/gitignore +0 -5
- package/templates/project/tsconfig.json +0 -13
- package/templates/single-site/checks.ts +0 -26
- package/templates/single-site/circuit.config.ts +0 -8
- package/templates/single-site/router.ts +0 -86
- package/templates/single-site/site.ts +0 -18
- package/templates/single-site/switch.ts +0 -34
- /package/src/studio/{public → app/public}/favicon.svg +0 -0
- /package/src/studio/{public → app/public}/special-gothic-latin-ext.woff2 +0 -0
- /package/src/studio/{public → app/public}/special-gothic-latin.woff2 +0 -0
- /package/src/studio/{public → app/public}/special-gothic-license.txt +0 -0
package/dist/index.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Utils2,
|
|
3
|
-
Secrets2
|
|
4
|
-
} from "./chunks/index-3b343xva.js";
|
|
5
|
-
import {
|
|
6
|
-
Address2
|
|
7
|
-
} from "./chunks/index-n7w3tg5y.js";
|
|
8
|
-
|
|
9
|
-
// src/core/define.ts
|
|
10
|
-
var secret = (name) => ({ secret: name });
|
|
11
|
-
var secretFile = (path) => {
|
|
12
|
-
if (!/^[A-Za-z0-9_./-]+$/.test(path))
|
|
13
|
-
throw new Error(`secret file path ${path} may hold only letters, digits, _ . / and -`);
|
|
14
|
-
return { secret_file: path };
|
|
15
|
-
};
|
|
16
|
-
function defineDevice(device) {
|
|
17
|
-
return device;
|
|
18
|
-
}
|
|
19
|
-
var defineNetwork = (network) => network;
|
|
20
|
-
export {
|
|
21
|
-
Address2 as Address,
|
|
22
|
-
Secrets2 as Secrets,
|
|
23
|
-
Utils2 as Utils,
|
|
24
|
-
defineDevice,
|
|
25
|
-
defineNetwork,
|
|
26
|
-
secret,
|
|
27
|
-
secretFile
|
|
28
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Device } from "../schema/index.js";
|
|
2
|
-
/** One address or range in a segment, and what holds it. */
|
|
3
|
-
export type Use = {
|
|
4
|
-
/** An address, or `first-last` for a range. */
|
|
5
|
-
address: string;
|
|
6
|
-
what: string;
|
|
7
|
-
};
|
|
8
|
-
/** A prefix our devices have addresses in. */
|
|
9
|
-
export type Segment = {
|
|
10
|
-
prefix: string;
|
|
11
|
-
uses: Use[];
|
|
12
|
-
/** How many addresses no one uses, as a number written out, since an IPv6 count does not fit a JavaScript number. */
|
|
13
|
-
free: string;
|
|
14
|
-
/** The lowest free address, when there is one. */
|
|
15
|
-
next?: string;
|
|
16
|
-
};
|
|
17
|
-
/** A prefix in use without being a segment: a loopback's address, or a block routed elsewhere. */
|
|
18
|
-
export type Block = {
|
|
19
|
-
prefix: string;
|
|
20
|
-
what: string;
|
|
21
|
-
};
|
|
22
|
-
/** Space the network owns: a prefix it originates in BGP, or one asked for. Everything in use inside it, and what is free. */
|
|
23
|
-
export type Space = {
|
|
24
|
-
prefix: string;
|
|
25
|
-
/** Why it is listed, such as `originated by edge-01`. */
|
|
26
|
-
owner: string;
|
|
27
|
-
segments: Segment[];
|
|
28
|
-
blocks: Block[];
|
|
29
|
-
/** The fewest prefixes that cover what nothing uses. */
|
|
30
|
-
free: string[];
|
|
31
|
-
};
|
|
32
|
-
export type AddressReport = {
|
|
33
|
-
spaces: Space[];
|
|
34
|
-
/** What is in use outside every space. Left out when a prefix is asked for. */
|
|
35
|
-
elsewhere: {
|
|
36
|
-
segments: Segment[];
|
|
37
|
-
blocks: Block[];
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
export declare class AddressSpace {
|
|
41
|
-
private static isHostRoute;
|
|
42
|
-
private static numberOf;
|
|
43
|
-
/** Addresses a segment can give out: IPv4 leaves out the network and broadcast addresses below /31, and IPv6 the subnet-router anycast address. */
|
|
44
|
-
private static usable;
|
|
45
|
-
/** Ranges merged, so overlapping ones count once. */
|
|
46
|
-
private static merged;
|
|
47
|
-
/** What is inside `within` and not in any of the ranges. */
|
|
48
|
-
private static gaps;
|
|
49
|
-
/** `12` or, for a count too long to read, `about 2^64`, to the nearest power of two. */
|
|
50
|
-
private static count;
|
|
51
|
-
private static byAddress;
|
|
52
|
-
/** IPv4 before IPv6, then by first address. */
|
|
53
|
-
private static comparePrefixes;
|
|
54
|
-
private static byPrefix;
|
|
55
|
-
/** Every address in use, by segment, under the space the network owns. With `within`, only what falls inside that prefix, as the one space. */
|
|
56
|
-
static report(devices: readonly Device[], within?: string): AddressReport;
|
|
57
|
-
/** Free prefixes of one length inside the free space, up to `limit`, and how many there are in all. */
|
|
58
|
-
static freeOfLength(free: readonly string[], length: number, limit: number): {
|
|
59
|
-
prefixes: string[];
|
|
60
|
-
total: bigint;
|
|
61
|
-
};
|
|
62
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Family, IP, IPv4, Prefix } from "../schema/index.js";
|
|
2
|
-
/** Address helpers, for checks of your own. */
|
|
3
|
-
export declare class Address {
|
|
4
|
-
/** IPv4 space another network cannot reach: this host, private, shared, loopback, link-local and documentation, after RFC 6890. */
|
|
5
|
-
private static readonly NOT_GLOBAL_V4;
|
|
6
|
-
static family(address: string): Family;
|
|
7
|
-
/** How many bits an address of the family has: 32 or 128. */
|
|
8
|
-
static bits(family: Family): number;
|
|
9
|
-
/** An address as a number, or null when it is not one. */
|
|
10
|
-
static toNumber(address: string): bigint | null;
|
|
11
|
-
/** `10.0.0.1/24` to its parts. Throws when it is not an address with a length. */
|
|
12
|
-
static split(cidr: string): {
|
|
13
|
-
addr: string;
|
|
14
|
-
len: number;
|
|
15
|
-
family: Family;
|
|
16
|
-
};
|
|
17
|
-
static isValid(text: string): boolean;
|
|
18
|
-
static isCidr(text: string): boolean;
|
|
19
|
-
private static mask;
|
|
20
|
-
/** A number back to the address it stands for. */
|
|
21
|
-
static fromNumber(value: bigint, family: Family): IP;
|
|
22
|
-
/** An address, with or without its length, in one spelling: IPv6 as RFC 5952 writes it, so `2001:DB8:0:0::1` and `2001:db8::1` compare equal. Text that is not an address comes back as it is. */
|
|
23
|
-
static canonical(text: string): string;
|
|
24
|
-
/** `10.0.0.1/24` to `10.0.0.0/24`. */
|
|
25
|
-
static prefixOf(cidr: string): Prefix;
|
|
26
|
-
/** Is the address or prefix `inner` inside `outer`? */
|
|
27
|
-
static contains(outer: string, inner: string): boolean;
|
|
28
|
-
/** The first and last address of a prefix, as numbers. */
|
|
29
|
-
static range(cidr: string): {
|
|
30
|
-
first: bigint;
|
|
31
|
-
last: bigint;
|
|
32
|
-
family: Family;
|
|
33
|
-
};
|
|
34
|
-
/** The fewest prefixes that cover every address from `first` to `last` and nothing else. */
|
|
35
|
-
static prefixesBetween(first: bigint, last: bigint, family: Family): Prefix[];
|
|
36
|
-
/** `/25` to `255.255.255.128`. */
|
|
37
|
-
static netmask(length: number): IPv4;
|
|
38
|
-
/** `/24` to `0.0.0.255`, the inverted mask some ACLs take. */
|
|
39
|
-
static wildcard(length: number): IPv4;
|
|
40
|
-
/** The address with its length dropped. */
|
|
41
|
-
static host(cidr: string): IP;
|
|
42
|
-
/** Whether another network can reach the address. IPv6 is global only inside 2000::/3, less documentation space. */
|
|
43
|
-
static isGlobal(address: string): boolean;
|
|
44
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Device } from "../schema/index.js";
|
|
2
|
-
import type { Finding } from "./define.js";
|
|
3
|
-
/** A device one of our ports sees at the far end of its cable, over LLDP. */
|
|
4
|
-
export type Neighbor = {
|
|
5
|
-
/** Our port, by Circuit's name, such as `10g-1`. */
|
|
6
|
-
port: string;
|
|
7
|
-
/** The system name the far device sends, its hostname. */
|
|
8
|
-
system: string;
|
|
9
|
-
/** The far device's port, as that device spells it, such as `XGigabitEthernet0/0/1`. */
|
|
10
|
-
remote_port: string;
|
|
11
|
-
};
|
|
12
|
-
export declare class Cabling {
|
|
13
|
-
/** The end of a state file that holds a device's LLDP neighbors, beside its config. */
|
|
14
|
-
static readonly SUFFIX = ".lldp.json";
|
|
15
|
-
/** The file a device's neighbors are saved in. */
|
|
16
|
-
static path(stateDirectory: string, device: string): string;
|
|
17
|
-
/** Save what a device sees, sorted, so a file changes only when a neighbor does. */
|
|
18
|
-
static save(stateDirectory: string, device: string, neighbors: readonly Neighbor[]): void;
|
|
19
|
-
/** Forget what a device saw, when its neighbors could not be read this time. */
|
|
20
|
-
static forget(stateDirectory: string, device: string): void;
|
|
21
|
-
/** What a device saw at its last snapshot, or undefined when its neighbors were never read. */
|
|
22
|
-
static load(stateDirectory: string, device: string): Neighbor[] | undefined;
|
|
23
|
-
private static order;
|
|
24
|
-
/** The device runs LLDP somewhere: on every port, on the interfaces it lists, or on a port that turns it on. */
|
|
25
|
-
static runsAnywhere(device: Device): boolean;
|
|
26
|
-
/** The port runs LLDP, by the port's own `lldp`, or else the device's. */
|
|
27
|
-
static runsOn(device: Device, port: string): boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Warnings where LLDP and `link` disagree, from each device's own view: a cable in another port than `link` names, a cable `link` names that LLDP does not see, and another of our devices on a port without `link`.
|
|
30
|
-
*
|
|
31
|
-
* Only ports where both ends run LLDP, by the config, are compared, and only on devices whose neighbors were read. A link `through` a carrier is not compared. LLDP can be off at the far end, so each is a warning.
|
|
32
|
-
*/
|
|
33
|
-
static compare(devices: readonly Device[], neighbors: ReadonlyMap<string, readonly Neighbor[]>): Finding[];
|
|
34
|
-
/** A system name is the device's name, alone or with a domain after it. */
|
|
35
|
-
private static isDevice;
|
|
36
|
-
private static deviceOf;
|
|
37
|
-
/** A port LLDP reports, as the far device spells it, is that device's port by Circuit's name. */
|
|
38
|
-
private static isPort;
|
|
39
|
-
/** Circuit's name for a port LLDP reports, or the report itself when no port of the device is spelled that way. */
|
|
40
|
-
private static portOf;
|
|
41
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { Device } from "../schema/index.js";
|
|
2
|
-
import type { Finding } from "./define.js";
|
|
3
|
-
export declare class CrossChecks {
|
|
4
|
-
/** Every rule across devices. */
|
|
5
|
-
static run(devices: readonly Device[]): Finding[];
|
|
6
|
-
/** The VLAN ids a port or LAG carries, by how it carries them, so two ends can be compared across devices. */
|
|
7
|
-
private static carried;
|
|
8
|
-
/** How a port carries its VLANs, in words: "VLANs 10, 20 tagged and VLAN 30 untagged as native". */
|
|
9
|
-
private static describeCarried;
|
|
10
|
-
/** VLAN names by id, for the VLANs a port or LAG carries. */
|
|
11
|
-
private static vlanNames;
|
|
12
|
-
/** What a port's settings are kept on: the LAG when the port is a member of one, otherwise the port. */
|
|
13
|
-
private static carrierOf;
|
|
14
|
-
/** The plain addresses of one family on an interface, leaving out point-to-point ones. */
|
|
15
|
-
private static plainAddresses;
|
|
16
|
-
/** Why the two ends of a cable cannot reach each other by address, or undefined when they can. */
|
|
17
|
-
private static addressDisagreement;
|
|
18
|
-
/** A link names a device and port that exist, the far end links back through the same carrier, and both ends carry the same VLANs the same way, with the same MTU, speed and addresses. */
|
|
19
|
-
private static checkLinks;
|
|
20
|
-
/** No address is held by two devices in one VRF. Two loopbacks may hold one on purpose, for anycast, so that is a warning. */
|
|
21
|
-
private static checkAddresses;
|
|
22
|
-
/** A BGP session to an address another of our devices holds needs that device's session back, in the AS it expects, from the address it names. */
|
|
23
|
-
private static checkSessions;
|
|
24
|
-
/** On one segment, a VRRP id has one address and an address has one id, on every device. */
|
|
25
|
-
private static checkVrrp;
|
|
26
|
-
/** A GRE or VXLAN tunnel to another of our devices has a tunnel back there, with the endpoints mirrored and, for VXLAN, the same VNI and port. */
|
|
27
|
-
private static checkTunnels;
|
|
28
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { ModelName, PlatformName, PortName } from "../platforms/catalog.js";
|
|
2
|
-
import type { Device, Secret } from "../schema/index.js";
|
|
3
|
-
/** A value resolved by name when a device is applied, from the environment or `.env` beside the config, and through 1Password when that value is an `op://` reference. Never the value itself. */
|
|
4
|
-
export declare const secret: (name: string) => Secret;
|
|
5
|
-
/** A value read from a file when a device is applied, such as a private key in PEM. The path is relative to the config file; keep the file out of git. */
|
|
6
|
-
export declare const secretFile: (path: string) => Secret;
|
|
7
|
-
/**
|
|
8
|
-
* Declare one device.
|
|
9
|
-
*
|
|
10
|
-
* The names it declares (VLANs, interfaces, policies and the rest) are the only names its other fields accept, and the editor suggests them. The port names come from the model.
|
|
11
|
-
*/
|
|
12
|
-
export declare function defineDevice<const Platform extends PlatformName, const Model extends ModelName<Platform>, const Vlans extends string = never, const Interfaces extends string = never, const Policies extends string = never, const PrefixSets extends string = never, const BgpGroups extends string = never, const Acls extends string = never, const AddressSets extends string = never, const Users extends string = never, const Vrfs extends string = never, const Certificates extends string = never, const Tables extends string = never>(device: Device<Platform, Model, PortName<Platform, Model>, Vlans, Interfaces, Policies, PrefixSets, BgpGroups, Acls, AddressSets, Users, Vrfs, Certificates, Tables>): Device;
|
|
13
|
-
/** Something a check found. */
|
|
14
|
-
export type Finding = {
|
|
15
|
-
/** An error stops `diff` and `apply`; a warning is reported only. */
|
|
16
|
-
level: "error" | "warning";
|
|
17
|
-
/** The device it is about, when it is about one. */
|
|
18
|
-
device?: string;
|
|
19
|
-
/** What is wrong, in a sentence. */
|
|
20
|
-
message: string;
|
|
21
|
-
};
|
|
22
|
-
/** A rule of your own design, run by `validate` beside the framework's. */
|
|
23
|
-
export type Check = (devices: readonly Device[]) => readonly Finding[];
|
|
24
|
-
/**
|
|
25
|
-
* One BGP community the network defines, in the community description format of the NLNOG Ring looking glass, which bgp.tools also reads.
|
|
26
|
-
*
|
|
27
|
-
* `community` takes `nnn` for any number, `x` for one digit and `a-b` for a range, such as `65535:0:nnn`. `description` refers to what each wildcard matched as `$0`, `$1` and so on, such as `do not announce to AS$0`.
|
|
28
|
-
*/
|
|
29
|
-
export type Community = {
|
|
30
|
-
community: string;
|
|
31
|
-
description: string;
|
|
32
|
-
};
|
|
33
|
-
/** The whole network. */
|
|
34
|
-
export type Network = {
|
|
35
|
-
/** Every device the framework manages. */
|
|
36
|
-
devices: readonly Device[];
|
|
37
|
-
/** Rules of your own design. */
|
|
38
|
-
checks?: readonly Check[];
|
|
39
|
-
/** The AS the network operates, for what is published about it. */
|
|
40
|
-
asn?: number;
|
|
41
|
-
/** The BGP communities the network defines, printed by `circuit communities` for a looking glass or bgp.tools. */
|
|
42
|
-
communities?: readonly Community[];
|
|
43
|
-
/**
|
|
44
|
-
* The site each device is at, such as a data centre or an office, by name. Devices ignore it.
|
|
45
|
-
*
|
|
46
|
-
* `circuit netbox` puts the device on the NetBox site of that name, and `circuit librenms` puts it in a LibreNMS device group of that name.
|
|
47
|
-
*/
|
|
48
|
-
site?: (device: Device) => string;
|
|
49
|
-
/** Keeps the network's PeeringDB record in step with the config: `circuit peeringdb`. Needs `asn`. */
|
|
50
|
-
peeringdb?: {
|
|
51
|
-
/** An API key with write access to the network's record. */
|
|
52
|
-
api_key: Secret;
|
|
53
|
-
};
|
|
54
|
-
/** Keeps LibreNMS monitoring every device, under its name, with its SNMP credentials and location, and in a group for its `site`: `circuit librenms`. */
|
|
55
|
-
librenms?: {
|
|
56
|
-
/** Where LibreNMS is, such as `https://librenms.example.com`. */
|
|
57
|
-
url: string;
|
|
58
|
-
/** An API token that can add and change devices and device groups. */
|
|
59
|
-
api_token: Secret;
|
|
60
|
-
};
|
|
61
|
-
/** Keeps NetBox in step with the config: `circuit netbox`. Needs `site`. */
|
|
62
|
-
netbox?: {
|
|
63
|
-
/** Where NetBox is, such as `https://netbox.example.com`. */
|
|
64
|
-
url: string;
|
|
65
|
-
/** An API token that can write. */
|
|
66
|
-
api_token: Secret;
|
|
67
|
-
/** What NetBox needs to know about a device that its config does not say. */
|
|
68
|
-
device: (device: Device) => NetBoxDevice;
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
|
-
/** What NetBox needs to know about a device that its config does not say. */
|
|
72
|
-
export type NetBoxDevice = {
|
|
73
|
-
/** The device role's name in NetBox, such as `Core switch`. Circuit makes the role when NetBox has none of that name. */
|
|
74
|
-
role: string;
|
|
75
|
-
/** The device type's model name in NetBox, made by the platform's vendor. The device's `model` when absent. */
|
|
76
|
-
device_type?: string;
|
|
77
|
-
};
|
|
78
|
-
/** Declare the network, in `circuit.config.ts`. */
|
|
79
|
-
export declare const defineNetwork: (network: Network) => Network;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare class ProjectFiles {
|
|
2
|
-
/** Directories that hold no config of the project's own. */
|
|
3
|
-
private static readonly SKIPPED;
|
|
4
|
-
/** The first name written out after a call to defineDevice: the device's own, not that of another device a link, a peer or a tunnel names further on. */
|
|
5
|
-
private static readonly FIRST_NAME;
|
|
6
|
-
/** Every TypeScript file of the project, relative to its root, in name order. */
|
|
7
|
-
static sources(root: string, directory?: string): string[];
|
|
8
|
-
/** Whether a file's text declares the device: it calls defineDevice and gives it the name, written out whole. */
|
|
9
|
-
static declaresDevice(text: string, name: string): boolean;
|
|
10
|
-
/** The project files that declare the device, relative to the root. */
|
|
11
|
-
static deviceFiles(root: string, name: string, sources?: string[]): string[];
|
|
12
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export type Field = {
|
|
2
|
-
path: string;
|
|
3
|
-
type: string;
|
|
4
|
-
description: string;
|
|
5
|
-
};
|
|
6
|
-
export type TypeDoc = {
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
definition?: string;
|
|
10
|
-
includes?: string[];
|
|
11
|
-
fields: Field[];
|
|
12
|
-
};
|
|
13
|
-
export declare class SchemaDocs {
|
|
14
|
-
/** The schema files in reading order, with the title each gets. */
|
|
15
|
-
static readonly FILES: readonly [readonly ["device.ts", "Device"], readonly ["interfaces.ts", "Ports and interfaces"], readonly ["routing.ts", "Routing"], readonly ["policy.ts", "Route policies"], readonly ["firewall.ts", "Firewall and ACLs"], readonly ["system.ts", "System and management"], readonly ["common.ts", "Common values"]];
|
|
16
|
-
/** The text of a JSDoc comment, without its markers, as one paragraph. */
|
|
17
|
-
private static commentText;
|
|
18
|
-
/** What a type parameter stands for, where it is not one of the device's names. */
|
|
19
|
-
private static readonly PARAMETER_MEANING;
|
|
20
|
-
/** A type as a reader needs it: "name" for each of the device's names, and no parameter list on the schema's own types. */
|
|
21
|
-
private static withoutGenerics;
|
|
22
|
-
private static parse;
|
|
23
|
-
/** Every type in each schema file, in the order given. Every file is read first, so a type is known to take parameters wherever it is used. */
|
|
24
|
-
static read(sources: readonly string[]): TypeDoc[][];
|
|
25
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Network } from "./define.js";
|
|
2
|
-
import type { Console, Device, IP, Secret } from "../schema/index.js";
|
|
3
|
-
/** How a device is logged in to: its management address and SSH port, its connection user and that user's password, and its console. */
|
|
4
|
-
export type DeviceLogin = {
|
|
5
|
-
/** Absent for a device reached only through its console. */
|
|
6
|
-
host?: IP;
|
|
7
|
-
port: number;
|
|
8
|
-
user: string;
|
|
9
|
-
/** The value, not a reference. Never print it. */
|
|
10
|
-
password: string;
|
|
11
|
-
console?: Console;
|
|
12
|
-
};
|
|
13
|
-
export declare class Secrets {
|
|
14
|
-
/** The directory of the config file. `.env` and secret files are found from here. */
|
|
15
|
-
private static root;
|
|
16
|
-
private static envFile;
|
|
17
|
-
private static readonly fromOnePassword;
|
|
18
|
-
/** Every value read in this run, so `scrub` can hide it. */
|
|
19
|
-
private static readonly revealed;
|
|
20
|
-
/** What `scrub` puts where a secret was. */
|
|
21
|
-
static readonly REDACTED = "<redacted>";
|
|
22
|
-
/** A value in `.env` shorter than this is not hidden: `.env` can hold settings that are not secrets, and hiding a short one would garble the text. */
|
|
23
|
-
private static readonly SHORTEST_DOTENV_VALUE;
|
|
24
|
-
/** A marker anywhere in a command. Its group is the reference. */
|
|
25
|
-
static readonly MARKER: RegExp;
|
|
26
|
-
/** Find `.env` and secret files from this directory, the config file's, instead of the working directory. */
|
|
27
|
-
static useRoot(directory: string): void;
|
|
28
|
-
/** `.env` beside the config, read once. Node and Bun read it the same way they load `.env` themselves: a `#` starts a comment unless the value is quoted. */
|
|
29
|
-
private static dotenv;
|
|
30
|
-
/** An unquoted value is cut at a `#`. A `#` after a space is a comment, but one inside the value, as in `abc#def`, would cut a password short and send that to a device, so it stops the run and asks for quotes. */
|
|
31
|
-
private static refuseCutValues;
|
|
32
|
-
/** Read a 1Password reference with the 1Password CLI, `op`, once per run. */
|
|
33
|
-
private static readOnePassword;
|
|
34
|
-
static isSecret(value: unknown): value is Secret;
|
|
35
|
-
/** How a reference is written inside a marker: a variable's name, or `file:` and a path. */
|
|
36
|
-
static referenceOf(secret: Secret): string;
|
|
37
|
-
/** Where a reference's value comes from, such as `.env` or `1Password, through .env`, without reading it. Undefined when it is set nowhere. */
|
|
38
|
-
static sourceOf(reference: string): string | undefined;
|
|
39
|
-
/** The value behind a reference, as `referenceOf` writes it: one marker's reference, for a platform that takes a secret interactively. */
|
|
40
|
-
static valueOf(reference: string): string;
|
|
41
|
-
/** The value of a secret, or of a variable named directly: from the environment, `.env`, 1Password or a file. */
|
|
42
|
-
static reveal(secret: Secret | string): string;
|
|
43
|
-
/** Every secret reference in a value, however deep, such as a network or one device, as `referenceOf` writes it. */
|
|
44
|
-
static referencesIn(value: unknown, found?: Set<string>): Set<string>;
|
|
45
|
-
/**
|
|
46
|
-
* Text with every secret value Circuit knows replaced by `<redacted>`, before it is printed. Devices echo what they are sent, passwords too.
|
|
47
|
-
*
|
|
48
|
-
* Hidden are: each value in `.env` of at least six characters, each value read in this run (1Password reads and secret files among them), each secret of `network` that the environment, `.env` or a file holds, and `extra`. A 1Password reference not read in this run is not read for this.
|
|
49
|
-
*/
|
|
50
|
-
static scrub(text: string, options?: {
|
|
51
|
-
network?: Network;
|
|
52
|
-
extra?: readonly string[];
|
|
53
|
-
}): string;
|
|
54
|
-
/** The value behind a reference when it can be had without asking anyone: a 1Password reference only once read in this run. Undefined otherwise. */
|
|
55
|
-
private static storedValueOf;
|
|
56
|
-
/** How Circuit logs in to a device: its address, port, connection user, that user's password revealed, and its console. */
|
|
57
|
-
static loginOf(device: Device): DeviceLogin;
|
|
58
|
-
/** How a secret appears in rendered config. Replaced with its value only when sent to a device. */
|
|
59
|
-
static marker(secret: Secret): string;
|
|
60
|
-
/** Replace every marker in a command with its value. */
|
|
61
|
-
static substitute(text: string): string;
|
|
62
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import type { Device, Routed } from "../schema/index.js";
|
|
2
|
-
import type { Finding } from "./define.js";
|
|
3
|
-
/** One view of the network. Every edge belongs to one. */
|
|
4
|
-
export type Layer = "l1" | "l2" | "l3" | "bgp" | "ospf" | "tunnels";
|
|
5
|
-
/** One of our devices, a segment several of them share, or something outside the network. */
|
|
6
|
-
export type GraphNode = {
|
|
7
|
-
/** Unique among the nodes, such as `device:edge-01` or `as:64501`. */
|
|
8
|
-
id: string;
|
|
9
|
-
kind: "device" | "segment" | "outside";
|
|
10
|
-
/** A word or two, drawn on the node. */
|
|
11
|
-
label: string;
|
|
12
|
-
/** One fact per line, for a closer look. */
|
|
13
|
-
detail: string[];
|
|
14
|
-
};
|
|
15
|
-
/** A VLAN a cable carries. */
|
|
16
|
-
export type CarriedVlan = {
|
|
17
|
-
name: string;
|
|
18
|
-
id: number;
|
|
19
|
-
/** Carried without a tag: the access VLAN, or a trunk's native VLAN. */
|
|
20
|
-
untagged: boolean;
|
|
21
|
-
};
|
|
22
|
-
export type GraphEdge = {
|
|
23
|
-
layer: Layer;
|
|
24
|
-
/** Node ids. */
|
|
25
|
-
from: string;
|
|
26
|
-
to: string;
|
|
27
|
-
/** A few words, drawn on the edge. */
|
|
28
|
-
label: string;
|
|
29
|
-
/** One fact per line, for a closer look. */
|
|
30
|
-
detail: string[];
|
|
31
|
-
/** Only one end declares it: the far device does not declare the cable, session or tunnel back. */
|
|
32
|
-
oneSided?: true;
|
|
33
|
-
/** On `l2`, the VLANs the cable carries. */
|
|
34
|
-
vlans?: CarriedVlan[];
|
|
35
|
-
};
|
|
36
|
-
export type Graph = {
|
|
37
|
-
nodes: GraphNode[];
|
|
38
|
-
edges: GraphEdge[];
|
|
39
|
-
};
|
|
40
|
-
/** How a device compares with its last snapshot, found offline as `diff` finds it. */
|
|
41
|
-
export type Drift = {
|
|
42
|
-
status: "matches" | "differs" | "no snapshot" | "cannot plan";
|
|
43
|
-
/** The plan `diff` would show, when it differs. */
|
|
44
|
-
lines: string[];
|
|
45
|
-
};
|
|
46
|
-
/** The graph with what `validate` found and how each device drawn compares with its snapshot. */
|
|
47
|
-
export type Annotated = Graph & {
|
|
48
|
-
findings: Finding[];
|
|
49
|
-
/** By device name. */
|
|
50
|
-
drift: Record<string, Drift>;
|
|
51
|
-
};
|
|
52
|
-
/** An address one of the devices holds on a port or interface. */
|
|
53
|
-
export type Holder = {
|
|
54
|
-
device: Device;
|
|
55
|
-
/** The port or interface. */
|
|
56
|
-
name: string;
|
|
57
|
-
/** With its length. */
|
|
58
|
-
address: string;
|
|
59
|
-
/** The far end of a point-to-point address. */
|
|
60
|
-
peer?: string;
|
|
61
|
-
vrrp: NonNullable<Routed<string>["vrrp"]>;
|
|
62
|
-
/** The VRF the address is in. The default table when absent. */
|
|
63
|
-
vrf?: string;
|
|
64
|
-
};
|
|
65
|
-
export declare class Topology {
|
|
66
|
-
static readonly LAYERS: readonly Layer[];
|
|
67
|
-
static deviceId(name: string): string;
|
|
68
|
-
/** An address as a key, so two spellings of one address compare equal. Undefined when it is not an address. */
|
|
69
|
-
static keyOf(address: string | undefined): string | undefined;
|
|
70
|
-
private static isHostRoute;
|
|
71
|
-
/** Ports, then interfaces, that can hold an address. */
|
|
72
|
-
static routedOf(device: Device): [string, Routed<string>][];
|
|
73
|
-
/** Every valid address the devices hold. An invalid one is left for `validate` to report. */
|
|
74
|
-
static holders(devices: readonly Device[]): Holder[];
|
|
75
|
-
private static describeDevice;
|
|
76
|
-
/** The VLANs a port or LAG carries, by id. */
|
|
77
|
-
private static carriedBy;
|
|
78
|
-
private static vlanLabel;
|
|
79
|
-
/** `l1`, every cable, with a LAG's member cables as one edge; and `l2`, the VLANs each one carries. */
|
|
80
|
-
private static cables;
|
|
81
|
-
/** `l3`: prefixes several devices hold an address in, and point-to-point addresses whose far end is another device. */
|
|
82
|
-
private static segments;
|
|
83
|
-
/** `bgp`: sessions between our devices, matched by the address each names, and to every AS outside. */
|
|
84
|
-
private static sessions;
|
|
85
|
-
/** `ospf`: two devices with OSPF on interfaces in one area and one prefix, neither passive. */
|
|
86
|
-
private static adjacencies;
|
|
87
|
-
/** `host:port` or `[host]:port` to the host. */
|
|
88
|
-
private static endpointHost;
|
|
89
|
-
/** `tunnels`: GRE and VXLAN tunnels matched by their endpoints, and WireGuard peers matched to the device at the far end. */
|
|
90
|
-
private static tunnels;
|
|
91
|
-
private static wireguard;
|
|
92
|
-
/** The network as a graph. It reads the config only, never a device, and works on a config that does not validate. */
|
|
93
|
-
static of(devices: readonly Device[]): Graph;
|
|
94
|
-
/** Only the edges on these layers, and among those only the ones that touch these devices when any are named. Every device named stays. */
|
|
95
|
-
static only(graph: Graph, layers: readonly Layer[], deviceNames?: readonly string[]): Graph;
|
|
96
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
type Merged<T extends readonly object[]> = T extends readonly [infer Head, ...infer Tail extends readonly object[]] ? Head & Merged<Tail> : unknown;
|
|
2
|
-
export declare class Utils {
|
|
3
|
-
/** Combine records into one, such as a device's own interfaces and those a module derives for it. Unlike spreading them, a name two of them hold is an error rather than one silently replacing the other. */
|
|
4
|
-
static merge<const T extends readonly Record<string, unknown>[]>(...records: T): Merged<T>;
|
|
5
|
-
/** The table a route or a BGP session is in, beside the main one: `undefined` for the main table, written `main` or left out. */
|
|
6
|
-
static otherTable(table: string | undefined): string | undefined;
|
|
7
|
-
/** Minutes east of UTC an IANA zone is at now, for platforms that take an offset rather than a zone. */
|
|
8
|
-
static timeZoneOffset(zone: string): number;
|
|
9
|
-
}
|
|
10
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { Finding, Network } from "./define.js";
|
|
2
|
-
export declare class Validator {
|
|
3
|
-
static run(network: Network): Finding[];
|
|
4
|
-
private static checkDevice;
|
|
5
|
-
/** A management VDOM: FortiOS only, not `root`, with declared interfaces, and routes that leave through its own. */
|
|
6
|
-
private static checkVdoms;
|
|
7
|
-
/** What the model's hardware holds, from the catalog. A LAG with too many members is an error; too many switch rules is a warning, since the limit is only roughly known. */
|
|
8
|
-
private static checkLimits;
|
|
9
|
-
private static checkVlans;
|
|
10
|
-
/** Every address is valid, and no address sits on two interfaces of one routing table. Two VRFs may hold the same address. */
|
|
11
|
-
private static checkAddresses;
|
|
12
|
-
private static checkPorts;
|
|
13
|
-
/** A MAC limit is a whole number above 0, and an ethertype filter lets at least one kind in, each once. */
|
|
14
|
-
private static checkFrames;
|
|
15
|
-
private static checkInterfaces;
|
|
16
|
-
private static checkRouting;
|
|
17
|
-
/** Routing tables have names of their own and something installing routes in them, and rules name a table and can each be reached. */
|
|
18
|
-
private static checkTables;
|
|
19
|
-
private static checkPolicies;
|
|
20
|
-
private static checkFirewall;
|
|
21
|
-
private static checkServices;
|
|
22
|
-
private static checkCertificates;
|
|
23
|
-
}
|