Skip to content

Commit

Permalink
feat(IPAM): More TypeScript Access to YAML
Browse files Browse the repository at this point in the history
  • Loading branch information
EntraptaJ committed Jan 23, 2021
1 parent a01f613 commit 53bce87
Show file tree
Hide file tree
Showing 15 changed files with 266 additions and 75 deletions.
2 changes: 1 addition & 1 deletion schemas/IPAM.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"$schema":"http://json-schema.org/draft-07/schema#","definitions":{"community":{"type":"object","additionalProperties":false,"$id":"#community","description":"Community","properties":{"contact":{"type":"string","description":"Community Contact ID"},"name":{"type":"string","description":"Community Friendly Name"},"id":{"type":"string","description":"Short form community code","examples":["sxl"]},"sites":{"type":"array","items":{"$ref":"#/definitions/communitySite"}}},"required":["name","id","sites"]},"communitySite":{"type":"object","additionalProperties":false,"description":"Community Site","properties":{"id":{"type":"string","description":"Site short id"},"name":{"type":"string"},"devices":{"type":"array","items":{"$ref":"#/definitions/device"}}},"required":["id","name"]},"contact":{"type":"object","additionalProperties":false,"$id":"#contact","description":"Community Contact","properties":{"id":{"type":"string","description":"Unique contact ID"},"name":{"type":"string","description":"Contact Full Name"}},"required":["id","name"]},"device":{"type":"object","additionalProperties":false,"$id":"#device","description":"Network Device","properties":{"id":{"type":"string","description":"Chained ID"},"name":{"type":"string","description":"Friendly name"},"type":{"$ref":"#/definitions/networkDeviceType"}},"required":["id","name"]},"networkcircuit":{"type":"object","additionalProperties":false,"description":"NetworkCircuit","properties":{"id":{"type":"string","description":"Circuit Id"},"speed":{"type":"string","description":"Circuit Speed"}},"required":["id"]},"networkDeviceLink":{"type":"object","additionalProperties":false,"description":"Link a Network to a device","properties":{"id":{"type":"string","description":"Device id"},"interface":{"type":"string","description":"Device interface"}},"required":["id"]},"circuitLocation":{"type":"object","description":"Traditional external circuits","properties":{"id":{"type":"string","description":"External circuit id"},"provider":{"type":"string","description":"External circuit provider"},"communuity":{"type":"string","description":"Community ID"},"address":{"type":"string","description":"Address provided to external provider"},"demarcSpeed":{"type":"string","enum":["10M","100M","200M","300M","500M","1G","5G","10G"]}}},"circuit":{"type":"object","description":"Community Circuit","properties":{"id":{"type":"string","description":"Circuit ID"},"sideA":{"type":"object","properties":{"id":{"type":"string","description":"Circuit Location Id"}}},"sideZ":{"type":"object","properties":{"id":{"type":"string","description":"Circuit Location Id"}}},"speed":{"type":"string"}},"required":["id"]},"network":{"type":"object","additionalProperties":false,"description":"Network","properties":{"prefix":{"type":"string","description":"Network Prefix"},"description":{"type":"string"},"circuit":{"$ref":"#/definitions/networkcircuit"},"contact":{"type":"string","description":"Contact ID"},"hosts":{"type":"array","items":{"type":"object","additionalProperties":false,"description":"Indivual Network host","properties":{"ip":{"type":"string","description":"Host IP Address"},"hostname":{"type":"string","description":"Hostname for reverse DNS creation"},"description":{"type":"string"},"device":{"$ref":"#/definitions/networkDeviceLink"}},"required":["ip"]}},"ranges":{"type":"array","items":{"type":"object","additionalProperties":false,"description":"Network Range","properties":{"start":{"type":"string"},"end":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["DHCP","RESERVED","STATIC"]}},"required":["start","end"]}},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Children Networks"}}},"networkDeviceType":{"type":"string","enum":["router","switch","access-point","server","modem","firewall"]},"networkDeviceInterfaceType":{"type":"string","enum":["FastEthernet","GigabitEthernet","TenGigabitEthernet"]}},"type":"object","additionalProperties":false,"description":"IPAM Configuration File","properties":{"communities":{"type":"array","items":{"$ref":"#/definitions/community"}},"circuits":{"type":"array","items":{"$ref":"#/definitions/circuit"},"uniqueItems":true,"description":"Circuits"},"circuitLocations":{"type":"array","items":{"$ref":"#/definitions/circuitLocation"},"uniqueItems":true,"description":"External Circuits"},"contacts":{"type":"array","items":{"$ref":"#/definitions/contact"},"uniqueItems":true,"description":"Contact Information"},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Networks"}},"required":["communities","circuits","circuitLocations","contacts","networks"]}
{"$schema":"http://json-schema.org/draft-07/schema#","definitions":{"community":{"type":"object","additionalProperties":false,"$id":"#community","description":"Community","properties":{"contact":{"type":"string","description":"Community Contact ID"},"name":{"type":"string","description":"Community Friendly Name"},"id":{"type":"string","description":"Short form community code","examples":["sxl"]},"sites":{"type":"array","items":{"$ref":"#/definitions/communitySite"}}},"required":["name","id","sites"]},"communitySite":{"type":"object","additionalProperties":false,"description":"Community Site","properties":{"id":{"type":"string","description":"Site short id"},"name":{"type":"string"},"devices":{"type":"array","items":{"$ref":"#/definitions/device"}}},"required":["id","name"]},"contact":{"type":"object","additionalProperties":false,"$id":"#contact","description":"Community Contact","properties":{"id":{"type":"string","description":"Unique contact ID"},"name":{"type":"string","description":"Contact Full Name"}},"required":["id","name"]},"device":{"type":"object","additionalProperties":false,"$id":"#device","description":"Network Device","properties":{"id":{"type":"string","description":"Chained ID"},"name":{"type":"string","description":"Friendly name"},"type":{"$ref":"#/definitions/networkDeviceType"}},"required":["id","name"]},"networkcircuit":{"type":"object","additionalProperties":false,"description":"NetworkCircuit","properties":{"id":{"type":"string","description":"Circuit Id"},"speed":{"type":"string","description":"Circuit Speed"}},"required":["id"]},"networkDeviceLink":{"type":"object","additionalProperties":false,"description":"Link a Network to a device","properties":{"id":{"type":"string","description":"Device id"},"interface":{"type":"string","description":"Device interface"}},"required":["id"]},"circuitLocation":{"type":"object","description":"Traditional external circuits","additionalProperties":false,"properties":{"id":{"type":"string","description":"External circuit id"},"provider":{"type":"string","description":"External circuit provider"},"communuity":{"type":"string","description":"Community ID"},"address":{"type":"string","description":"Address provided to external provider"},"demarcSpeed":{"type":"string","enum":["10M","100M","200M","300M","500M","1G","5G","10G"]}}},"circuit":{"type":"object","description":"Community Circuit","additionalProperties":false,"properties":{"id":{"type":"string","description":"Circuit ID"},"sideA":{"$ref":"#/definitions/circuitSide"},"sideZ":{"$ref":"#/definitions/circuitSide"},"speed":{"type":"string"}},"required":["id","sideA","sideZ"]},"circuitSide":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","description":"Circuit Location Id"}},"required":["id"]},"network":{"type":"object","additionalProperties":false,"description":"Network","properties":{"prefix":{"type":"string","description":"Network Prefix"},"description":{"type":"string"},"circuit":{"$ref":"#/definitions/networkcircuit"},"contact":{"type":"string","description":"Contact ID"},"hosts":{"type":"array","items":{"$ref":"#/definitions/networkHost"}},"ranges":{"type":"array","items":{"$ref":"#/definitions/networkRange"}},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Children Networks"}}},"networkHost":{"type":"object","additionalProperties":false,"description":"Indivual Network host","properties":{"ip":{"type":"string","description":"Host IP Address"},"hostname":{"type":"string","description":"Hostname for reverse DNS creation"},"description":{"type":"string"},"device":{"$ref":"#/definitions/networkDeviceLink"}},"required":["ip"]},"networkRange":{"type":"object","additionalProperties":false,"description":"Network Range","properties":{"start":{"type":"string"},"end":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["DHCP","RESERVED","STATIC"]}},"required":["start","end"]},"networkDeviceType":{"type":"string","enum":["router","switch","access-point","server","modem","firewall"]},"networkDeviceInterfaceType":{"type":"string","enum":["FastEthernet","GigabitEthernet","TenGigabitEthernet"]}},"type":"object","additionalProperties":false,"description":"IPAM Configuration File","properties":{"communities":{"type":"array","items":{"$ref":"#/definitions/community"}},"circuits":{"type":"array","items":{"$ref":"#/definitions/circuit"},"uniqueItems":true,"description":"Circuits"},"circuitLocations":{"type":"array","items":{"$ref":"#/definitions/circuitLocation"},"uniqueItems":true,"description":"External Circuits"},"contacts":{"type":"array","items":{"$ref":"#/definitions/contact"},"uniqueItems":true,"description":"Contact Information"},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Networks"}},"required":["communities","circuits","circuitLocations","contacts","networks"]}
27 changes: 27 additions & 0 deletions src/Modules/Circuits/Circuit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// src/Modules/Circuits/Circuit.ts
import Container, { Service } from 'typedi';
import {
Circuit as IPAMCircuit,
CircuitSide as IPAMCircuitSide,
} from '../IPAM/IPAMConfig.gen';

@Service()
export class Circuit implements IPAMCircuit {
public id: string;

public sideA: IPAMCircuitSide;

public sideZ: IPAMCircuitSide;

public get sideACircuitLocation(): Circuit {
return Container.get(`circuitLocation-${this.sideA.id}`);
}

public get sideZCircuitLocation(): Circuit {
return Container.get(`circuitLocation-${this.sideZ.id}`);
}

public constructor(options: Partial<Circuit>) {
Object.assign(this, options);
}
}
16 changes: 16 additions & 0 deletions src/Modules/Circuits/CircuitLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// src/Modules/Circuits/CircuitLocation.ts
import { Service } from 'typedi';
import { CircuitLocation as IPAMCircuitLocation } from '../IPAM/IPAMConfig.gen';

@Service()
export class CircuitLocation implements IPAMCircuitLocation {
public id: string;

public address: string;

public provider: string;

public constructor(options: Partial<CircuitLocation>) {
Object.assign(this, options);
}
}
11 changes: 11 additions & 0 deletions src/Modules/Circuits/CircuitSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// src/Modules/CommunityCircuits/CommunityCircuitConfigSchema.ts
import jsonSchema from 'fluent-json-schema';

export const circuitSchema = jsonSchema
.object()
.description('Community Circuit')
.additionalProperties(false)
.prop('id', jsonSchema.string().description('Circuit ID').required())
.prop('sideA', jsonSchema.ref('#/definitions/circuitSide').required())
.prop('sideZ', jsonSchema.ref('#/definitions/circuitSide').required())
.prop('speed', jsonSchema.string());
10 changes: 10 additions & 0 deletions src/Modules/Circuits/CircuitSideSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// src/Modules/Circuits/CircuitSideSchema.ts
import jsonSchema from 'fluent-json-schema';

export const circuitSideSchema = jsonSchema
.object()
.additionalProperties(false)
.prop(
'id',
jsonSchema.string().description('Circuit Location Id').required(),
);
14 changes: 0 additions & 14 deletions src/Modules/Communities/CommunityCircuitConfigSchema.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/Modules/CommunityCircuits/CircuitLocationSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CommunityCircuitSpeed } from './CommunityCircuitSpeed';
export const circuitLocationSchema = jsonSchema
.object()
.description('Traditional external circuits')
.additionalProperties(false)
.prop('id', jsonSchema.string().description('External circuit id'))
.prop(
'provider',
Expand Down
8 changes: 0 additions & 8 deletions src/Modules/CommunityCircuits/CommunityCircuitConfig.ts

This file was deleted.

9 changes: 9 additions & 0 deletions src/Modules/IPAM/IPAM.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// src/Modules/IPAM/IPAM.ts

import { Service } from 'typedi';
import { Circuit } from '../Circuits/Circuit';
import { CircuitLocation } from '../Circuits/CircuitLocation';
import { Contact } from '../CommunityContacts/CommunityContact';
import { Network } from '../Networks/Network';
import { Community } from './Community';

@Service()
Expand All @@ -10,6 +13,12 @@ export class IPAM {

public communities: Community[];

public circuitLocations: CircuitLocation[];

public circuits: Circuit[];

public networks: Network[];

public constructor(options: Partial<IPAM>) {
Object.assign(this, options);
}
Expand Down
68 changes: 34 additions & 34 deletions src/Modules/IPAM/IPAMConfig.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,15 @@ export interface Circuit {
* Circuit ID
*/
id: string;
sideA?: {
/**
* Circuit Location Id
*/
id?: string;
[k: string]: unknown;
};
sideZ?: {
/**
* Circuit Location Id
*/
id?: string;
[k: string]: unknown;
};
sideA: CircuitSide;
sideZ: CircuitSide;
speed?: string;
[k: string]: unknown;
}
export interface CircuitSide {
/**
* Circuit Location Id
*/
id: string;
}
/**
* Traditional external circuits
Expand All @@ -118,7 +111,6 @@ export interface CircuitLocation {
*/
address?: string;
demarcSpeed?: "10M" | "100M" | "200M" | "300M" | "500M" | "1G" | "5G" | "10G";
[k: string]: unknown;
}
/**
* Community Contact
Expand Down Expand Up @@ -147,24 +139,8 @@ export interface Network {
* Contact ID
*/
contact?: string;
hosts?: {
/**
* Host IP Address
*/
ip: string;
/**
* Hostname for reverse DNS creation
*/
hostname?: string;
description?: string;
device?: NetworkDeviceLink;
}[];
ranges?: {
start: string;
end: string;
description?: string;
type?: "DHCP" | "RESERVED" | "STATIC";
}[];
hosts?: NetworkHost[];
ranges?: NetworkRange[];
/**
* Children Networks
*/
Expand All @@ -183,6 +159,21 @@ export interface Networkcircuit {
*/
speed?: string;
}
/**
* Indivual Network host
*/
export interface NetworkHost {
/**
* Host IP Address
*/
ip: string;
/**
* Hostname for reverse DNS creation
*/
hostname?: string;
description?: string;
device?: NetworkDeviceLink;
}
/**
* Link a Network to a device
*/
Expand All @@ -196,3 +187,12 @@ export interface NetworkDeviceLink {
*/
interface?: string;
}
/**
* Network Range
*/
export interface NetworkRange {
start: string;
end: string;
description?: string;
type?: "DHCP" | "RESERVED" | "STATIC";
}
97 changes: 85 additions & 12 deletions src/Modules/IPAM/IPAMConfigController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@ import { load } from 'js-yaml';
import Container, { Service } from 'typedi';
import { logger, LogMode } from '../../Library/Logger';
import { isObjectType } from '../../Utils/isTypes';
import { Circuit } from '../Circuits/Circuit';
import { CircuitLocation } from '../Circuits/CircuitLocation';
import { CommunitySite } from '../Communities/CommunitySite';
import { Contact } from '../CommunityContacts/CommunityContact';
import { NetworkDevice } from '../NetworkDevices/NetworkDevice';
import { Network } from '../Networks/Network';
import { NetworkHost } from '../Networks/NetworkHost';
import { Community } from './Community';
import { IPAM } from './IPAM';
import {
IPAM,
IPAM as IPAMType,
Community as IPAMCommunity,
Contact as IPAMContact,
CommunitySite as IPAMCommunitySite,
Device as IPAMDevice,
Circuit as IPAMCircuit,
CircuitLocation as IPAMCircuitLocation,
Network as IPAMNetwork,
NetworkHost as IPAMNetworkHost,
} from './IPAMConfig.gen';

@Service()
Expand Down Expand Up @@ -67,6 +76,66 @@ export class IPAMConfigController {
});
}

public processCircuitLocations(
circuitLocations: IPAMCircuitLocation[],
): CircuitLocation[] {
return circuitLocations.map((circuitLocationValues) => {
const circuitLocation = new CircuitLocation(circuitLocationValues);

Container.set(`circuitLocation-${circuitLocation.id}`, circuitLocation);

return circuitLocation;
});
}

public processCircuits(circuits: IPAMCircuit[]): Circuit[] {
return circuits.map((circuitValues) => {
const circuit = new Circuit(circuitValues);

Container.set(`circuit-${circuit.id}`, circuit);

return circuit;
});
}

public processNetworkHosts(networkHosts: IPAMNetworkHost[]): NetworkHost[] {
return networkHosts.map((networkHostValue) => {
const networkHost = new NetworkHost(networkHostValue);

Container.set(`networkHost-${networkHost.ip}`, networkHost);

return networkHost;
});
}

public processNetworks(networks: IPAMNetwork[]): Network[] {
return networks.flatMap(
({
circuit,
networks: subNetworksValues,
hosts: hostsValue,
...networkValues
}) => {
const subNetworks = subNetworksValues
? this.processNetworks(subNetworksValues)
: [];

const hosts = hostsValue ? this.processNetworkHosts(hostsValue) : [];

const network = new Network({
circuitId: circuit?.id,
networks: subNetworks,
hosts,
...networkValues,
});

Container.set(`network-${network.prefix}`, network);

return [network, ...subNetworks];
},
);
}

/**
* Load the configured firewalls configuration file from disk, parse the YAML and load into the class
*/
Expand All @@ -77,7 +146,7 @@ export class IPAMConfigController {

const ipamConfigFile = load(ipamFile.toString());

if (isObjectType<IPAM>(ipamConfigFile, 'communities')) {
if (isObjectType<IPAMType>(ipamConfigFile, 'communities')) {
logger.log(
LogMode.INFO,
'Loaded Communities Configuration File',
Expand All @@ -89,19 +158,23 @@ export class IPAMConfigController {
const contacts = this.processContacts(ipamConfigFile.contacts);
const communities = this.processCommunities(ipamConfigFile.communities);

const torontoCommunity = communities.find(
({ name }) => name === 'Toronto',
const circuitLocations = this.processCircuitLocations(
ipamConfigFile.circuitLocations,
);

if (torontoCommunity) {
const device = torontoCommunity.sites[0].devices[0];
const circuits = this.processCircuits(ipamConfigFile.circuits);
const networks = this.processNetworks(ipamConfigFile.networks);

const ipam = new IPAM({
circuitLocations,
circuits,
communities,
contacts,
networks,
});

logger.log(
LogMode.DEBUG,
'Toronto: ',
device,
Container.get(`networkDevice-${device.id}`),
);
for (const network of ipam.networks) {
network.hosts.map((networkHost) => console.log(networkHost.coreDevice));
}

return;
Expand Down
Loading

0 comments on commit 53bce87

Please sign in to comment.