Skip to content

Commit

Permalink
Merge pull request #28 from f5devcentral/v1.6.0
Browse files Browse the repository at this point in the history
V1.6.0
  • Loading branch information
DumpySquare authored Apr 3, 2024
2 parents 0d5f391 + 6e570f0 commit d5b5cd8
Show file tree
Hide file tree
Showing 12 changed files with 549 additions and 46 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
### Fixed


---

## [1.6.0] - (04-03-2024)

### Fixed

- [Bug] Missing "add server" from "bind serviceGroup" reference
- Bug when config is missing title information with code version
- defaults to v13.0
- Bug when config is missing hostname (should use filename instead)
- Moved conversion codeLense from preview to main
- added test for serviceGroup abstraction

---

## [1.5.0] - (03-25-2024)
Expand Down
Binary file modified f5_flipper_test.tgz
Binary file not shown.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "F5 Flipper",
"description": "Breaking down Citrix NetScaler ADC configs",
"publisher": "F5DevCentral",
"version": "1.5.0",
"version": "1.6.0",
"keywords": [
"F5",
"F5Networks",
Expand Down
21 changes: 16 additions & 5 deletions src/CitrixADC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default class ADC extends EventEmitter {
* hostname of the source device
*/
public hostname: string | undefined;
/**
* input file name
*/
public inputFile: string;
/**
* input file type (.conf/.tgz)
*/
Expand Down Expand Up @@ -76,6 +80,9 @@ export default class ADC extends EventEmitter {
// capture incoming file type
this.inputFileType = path.parse(file).ext;

// capture input file name
this.inputFile = path.parse(file).name;

const parseConfPromises: any[] = [];
const parseStatPromises: any[] = [];
const unPacker = new UnPacker();
Expand Down Expand Up @@ -136,9 +143,11 @@ export default class ADC extends EventEmitter {
await parseAdcConfArrays(config, this.configObjectArry, this.rx!)

// get hostname from configObjectArry, assign to parent class for easy access
if (this.configObjectArry.set?.ns?.hostName.length > 0) {
if (this.configObjectArry.set?.ns?.hostName) {
// there should always be only one in this array
this.hostname = this.configObjectArry.set.ns.hostName[0];
} else {
this.hostname = this.inputFile;
}

// gather stats on the number of different objects found (vservers/monitors/policies)
Expand All @@ -161,8 +170,6 @@ export default class ADC extends EventEmitter {

// get adc version
[this.adcVersion, this.adcBuild] = this.getAdcVersion(x.content, rex.adcVersionBaseReg);

intLogger.info(`Recieved .conf file of version: ${this.adcVersion}`)

// assign regex tree for particular version
this.rx = rex.get(this.adcVersion)
Expand Down Expand Up @@ -288,12 +295,16 @@ export default class ADC extends EventEmitter {
if (version) {
//found adc version, grab build (split off first line, then split build by spaces)
const build = config.split('\n')[0].split(' ')[2]

intLogger.info(`Recieved .conf file of version: ${this.adcVersion}`)

// return details
return [version[1], build];
} else {
const msg = 'citrix adc/ns version not detected -> meaning this probably is not an ns.conf'
const msg = 'citrix adc/ns version not detected, defaulting to v13.0'
intLogger.error(msg)
throw new Error(msg)
return ['13.0', '000'];
// throw new Error(msg)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/codeLens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class NsCodeLensProvider implements CodeLensProvider {
)
);

} else if(document.fileName === 'app.ns.json' && ext.settings.preview) {
} else if(document.fileName === 'app.ns.json') {
// if document.name === 'app.ns.conf'

// find the editor -> get first line of text and abstract the appName
Expand Down
84 changes: 48 additions & 36 deletions src/digLbVserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function digLbVserver(coa: AdcConfObj, rx: AdcRegExTree) {

const apps: AdcApp[] = [];

if(!coa.add?.lb?.vserver) return apps;
if (!coa.add?.lb?.vserver) return apps;

await Promise.all(coa.add?.lb?.vserver?.map(vServ => {
const parent = 'add lb vserver';
Expand Down Expand Up @@ -67,29 +67,32 @@ export async function digLbVserver(coa: AdcConfObj, rx: AdcRegExTree) {
return logger.error(`regex "${rx.parents[parent]}" - failed for line "${originalString}"`);
}

// todo: need to see if this references a "add service" or "add serviceGroup"

if (!app.bindings) app.bindings = {};
if (rxMatch.groups?.service) {

const serviceName = rxMatch.groups?.service;
// app.bindings.service.push(rxMatch.groups.service)

// dig service details
coa.add?.service?.filter(s => s.startsWith(serviceName))
.forEach(async x => {
const parent = 'add service';
const originalString = parent + ' ' + x;
app.lines.push(originalString);
const rxMatch = x.match(rx.parents[parent])
const opts = parseNsOptions(rxMatch.groups?.opts, rx);
if (!rxMatch) {
/* istanbul ignore next */
return logger.error(`regex "${rx.parents[parent]}" - failed for line "${originalString}"`);
}
// also get server reference under 'add server <name>'
if(rxMatch.groups.server) {

// dig server from serviceGroup server reference
await digServer(rxMatch.groups.server, app, coa, rx)
// dig service details -> do we have a service with this name?
const serviceD = coa.add?.service?.filter(s => serviceName)[0]
if (serviceD) {
// this should only ever find one
const parent = 'add service';
const originalString = parent + ' ' + serviceD;
app.lines.push(originalString);
const rxMatch = serviceD.match(rx.parents[parent])
const opts = parseNsOptions(rxMatch.groups?.opts, rx);
if (!rxMatch) {
/* istanbul ignore next */
return logger.error(`regex "${rx.parents[parent]}" - failed for line "${originalString}"`);
}
// also get server reference under 'add server <name>'
if (rxMatch.groups.server) {

// dig server from serviceGroup server reference
await digServer(rxMatch.groups.server, app, coa, rx)
.then(i => {
if (i) {
// rxMatch.groups.server.splice(1, 0, i)
Expand All @@ -103,25 +106,25 @@ export async function digLbVserver(coa: AdcConfObj, rx: AdcRegExTree) {
// port: memberRef[2]
// })
})
}
}

// if we have service details create array to put them
if (!app.bindings.service) {
app.bindings.service = [];
}
// if we have service details create array to put them
if (!app.bindings.service) {
app.bindings.service = [];
}

// push service details to app config
app.bindings.service.push({
name: serviceName,
protocol: rxMatch.groups.protocol,
port: rxMatch.groups.port,
server: rxMatch.groups.server,
address: rxMatch.groups.address,
opts
})
// push service details to app config
app.bindings.service.push({
name: serviceName,
protocol: rxMatch.groups.protocol,
port: rxMatch.groups.port,
server: rxMatch.groups.server,
address: rxMatch.groups.address,
opts
})


})
}

// dig serviceGroup details
await digServiceGroup(serviceName, app, coa, rx)
Expand Down Expand Up @@ -313,10 +316,18 @@ export async function digSslBinding(app: AdcApp, obj: AdcConfObj, rx: AdcRegExTr

const sslBindObj = []

const appName = app.name;

const appSslVservers = obj.bind?.ssl?.vserver?.filter(s => s.startsWith(appName))

// check ssl bindings
for await (const x of obj.bind?.ssl?.vserver) {
// for await (const x of obj.bind?.ssl?.vserver) {

// if (x.startsWith(app.name)) {
if (appSslVservers.length > 0) {
for await (const x of appSslVservers) {


if (x.startsWith(app.name)) {
const parent = 'bind ssl vserver';
const originalString = parent + ' ' + x;
app.lines.push(originalString);
Expand All @@ -339,9 +350,10 @@ export async function digSslBinding(app: AdcApp, obj: AdcConfObj, rx: AdcRegExTr
})

}
// deepmergeInto(sslBindObj, opts)
}
// deepmergeInto(sslBindObj, opts)
}
// }

if (sslBindObj.length > 0) {
app.bindings.certs = sslBindObj;
Expand Down
2 changes: 1 addition & 1 deletion src/regex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class RegExTree {
'set ns hostName': /(?<hostName>[\S ]+)/,
'set gslb vserver': /(?<name>\S+) (?<opts>[\S ]+)/,
'bind service': /(?<opts>[\S ]+)/,
'bind serviceGroup': /(?<name>\S+) ((?<serv>\S+ \d+)|(?<monitor>-monitorName \S+)|(?<opts>[\S ]+))/,
'bind serviceGroup': /(?<name>\S+) ((?<serv>\S+ (\d+|\*))|(?<monitor>-monitorName \S+)|(?<opts>[\S ]+))/,
'bind lb vserver': /(?<name>\S+) ((?<opts>-[\S ]+)|(?<service>[\S]+))/,
'bind cs vserver': /(?<server>\S+) (?<opts>[\S ]+)/,
'bind ssl vserver': /(?<server>\S+) (?<opts>[\S ]+)/,
Expand Down
124 changes: 124 additions & 0 deletions tests/025_serviceGroups.unit.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/*
* Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for
* license terms. Notwithstanding anything to the contrary in the EULA, Licensee
* may copy and modify this software product for its internal business purposes.
* Further, Licensee may upload, publish and distribute the modified version of
* the software product on devcentral.f5.com.
*/

'use strict';

import assert from 'assert';
import ADC from '../src/CitrixADC'
import { Explosion } from '../src/models';
import { archiveMake } from './archiveBuilder';

const events = [];
let testFile: string;

const parsedFileEvents: any[] = []
const parsedObjEvents: any[] = []

describe('serviceGroup abstraction tests', function () {

let adc: ADC;
let expld: Explosion;
let log;
let err;

before(async function () {
// log test file name - makes it easer for troubleshooting
console.log(' file:', __filename)
testFile = await archiveMake() as string;
// clear the events arrays
parsedFileEvents.length = 0
parsedObjEvents.length = 0
adc = new ADC();

adc.on('parseFile', x => parsedFileEvents.push(x))
adc.on('parseObject', x => parsedObjEvents.push(x))

await adc.loadParseAsync(testFile)
.then(async x => {
await adc.explode()
.then(x => {
expld = x
})
})
.catch(y => {
err = y;
log = adc.logs()
debugger;
})

});

afterEach(function () {
events.length = 0;
})



it(`basic serviceGroup reference`, async () => {

// cs -> bind ssl vserver groot-cs-vsvr -certkeyName star.groot.cer

// get application we are looking for
const app = expld.config.apps?.find(x => x.name === 'skree1_vip_RDP')

// get the serviceGroup details
const appServiceGroup = app!.bindings!.serviceGroup![0]

assert.deepStrictEqual(appServiceGroup, {
name: "skree1_servicegroup_RDP",
protocol: "RDP",
"-maxClient": "0",
"-maxReq": "0",
"-cip": "DISABLED",
"-usip": "YES",
"-useproxyport": "YES",
"-cltTimeout": "9000",
"-svrTimeout": "9000",
"-CKA": "NO",
"-TCPB": "NO",
"-CMP": "NO",
servers: [
{
name: "skree1server02",
address: "10.10.10.8",
port: "*",
},
{
name: "skree1server01",
address: "10.10.10.7",
port: "*",
},
],
})

})


// it(`lb ssl cert binding`, async () => {

// // lb -> bind ssl vserver starlord_offload_lb_vs -certkeyName starlord.galaxy.io_cert

// const app = expld.config.apps?.find(x => x.name === 'starlord_offload_lb_vs');

// // get the cert details
// const appCert = app?.bindings?.certs![0]

// assert.deepStrictEqual(appCert, {
// "-cert": "foo.crt",
// "-key": "foo.key",
// profileName: "starlord.galaxy.io_cert",
// })
// })

// // it(`vpn? ssl cert binding`, async () => {

// // // and ssl cert binding? like a service?
// // })

});
Loading

0 comments on commit d5b5cd8

Please sign in to comment.