f5-conx-core
Version:
F5 SDK for JavaScript with Typescript type definitions
345 lines • 16.6 kB
JavaScript
/* 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';
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.F5Client = void 0;
const events_1 = require("events");
// import { MetadataClient } from "./metadata";
const mgmtClient_1 = require("./mgmtClient");
const nextClientBase_1 = require("./nextClientBase");
const nextCmClientBase_1 = require("./nextCmClientBase");
const ucsClient_1 = require("./ucsClient");
const qkviewClient_1 = require("./qkviewClient");
const fastClient_1 = require("./fastClient");
const as3Client_1 = require("./as3Client");
const doClient_1 = require("./doClient");
const tsClient_1 = require("./tsClient");
const cfClient_1 = require("./cfClient");
const atcMgmtClient_1 = require("./atcMgmtClient");
const externalHttps_1 = require("../externalHttps");
const constants_1 = require("../constants");
const path_1 = __importDefault(require("path"));
const detectNextBigip_1 = require("./detectNextBigip");
/**
* Main F5 connectivity client
*
* Basic Example:
*
* ```
* const mgmtClient = new f5Client(
* host: '192.0.2.1',
* user: 'admin',
* password: 'admin',
* {
* port: 8443,
* provider: 'tmos'
* }
* );
* await f5Client.discover();
* const resp = await f5Client.makeRequest('/mgmt/tm/sys/version');
* ```
*/
class F5Client {
constructor(host, user, password, hostOptions, eventEmmiter, extHttp, teemEnv, teemAgent) {
/**
* ATC meta data including:
* * service endpoint information /info/declare/tasks
* * github releases url
* * github main repo url
*/
this.atcMetaData = constants_1.atcMetaData;
// setup cache dir
this.cacheDir = process.env.F5_CONX_CORE_CACHE || path_1.default.join(process.cwd(), constants_1.TMP_DIR);
// setup eventer
this.events = eventEmmiter ? eventEmmiter : new events_1.EventEmitter();
// setup external http class (feed it the events instance)
this.extHttp = extHttp ? extHttp : new externalHttps_1.ExtHttp({
eventEmitter: this.events,
});
this.mgmtClient = new mgmtClient_1.MgmtClient(host, user, password, hostOptions, eventEmmiter = this.events, teemEnv, teemAgent);
}
/**
* clear auth token
* - mainly for unit tests...
*/
clearLogin() {
return __awaiter(this, void 0, void 0, function* () {
return yield this.mgmtClient.clearToken();
});
}
/**
* Make HTTP request
*
* @param uri request URI
* @param options function options
*
* @returns request response
*/
https(uri, options) {
return __awaiter(this, void 0, void 0, function* () {
const x = yield this.mgmtClient.makeRequest(uri, options);
return x;
});
}
/**
* discover information about device
* - bigip/bigiq/nginx?
* - tmos/nginx version
* - installed atc services and versions
*
*/
discover(product) {
return __awaiter(this, void 0, void 0, function* () {
const returnInfo = {};
// rework logic flow to something like
// 1. if no product provided at function call, discover product type
// 2. execute discovery as needed for each product type
// todo; enable a flag to bypass check if we know what we are connecting to
if (product === undefined) {
// discover if next/cm
yield (0, detectNextBigip_1.detectNextAsync)(this.mgmtClient.host)
.then(type => {
product = type.product;
this.events.emit('log-debug', `Next/CM detected: ${JSON.stringify(type)}`);
})
.catch(err => {
// just log the error to prevent it from stopping the flow
this.events.emit('log-debug', `no Next/CM detected: ${err}`);
product = 'BIG-IP'; // as a default; we assume BIG-IP till we connect and know it's BIG-IQ
});
}
if (product === 'NEXT') {
this.mgmtClient = new nextClientBase_1.NextMgmtClient(this.mgmtClient.host, this.mgmtClient.user, this.mgmtClient.password, {
port: this.mgmtClient.port,
provider: this.mgmtClient.provider,
}, this.mgmtClient.events, this.mgmtClient.teemEnv, this.mgmtClient.teemAgent);
}
else if (product === 'NEXT-CM') {
// this is NEXT-CM
this.mgmtClient = new nextCmClientBase_1.NextCmMgmtClient(this.mgmtClient.host, this.mgmtClient.user, this.mgmtClient.password, {
port: this.mgmtClient.port,
provider: this.mgmtClient.provider,
}, this.mgmtClient.events, this.mgmtClient.teemEnv, this.mgmtClient.teemAgent);
}
this.mgmtClient.hostInfo = {
product
};
// hostname/product/version
returnInfo.product = product;
if (this.mgmtClient instanceof mgmtClient_1.MgmtClient) {
// this is a classic bigip as defined by the class type
// this means that we only discover things we KNOW are in classic AS OF 10/25/2022
// setup ucsClient
this.ucs = new ucsClient_1.UcsClient(this.mgmtClient);
// setup qkviewClient
this.qkview = new qkviewClient_1.QkviewClient(this.mgmtClient);
// setup atc rpm ilx mgmt
this.atc = new atcMgmtClient_1.AtcMgmtClient(this.mgmtClient, this.extHttp);
// get device info
yield this.mgmtClient.makeRequest('/mgmt/shared/identified-devices/config/device-info')
.then(resp => {
var _a, _b, _c;
// assign details to this and mgmtClient class
this.host = resp.data;
this.mgmtClient.hostInfo = resp.data;
returnInfo.hostname = (_a = this.host) === null || _a === void 0 ? void 0 : _a.hostname;
returnInfo.version = (_b = this.host) === null || _b === void 0 ? void 0 : _b.version;
returnInfo.product = (_c = this.host) === null || _c === void 0 ? void 0 : _c.product;
});
// check FAST installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.fast.endPoints.info)
.then(resp => {
this.fast = new fastClient_1.FastClient(resp.data, this.atcMetaData.fast, this.mgmtClient);
returnInfo.atc = {};
returnInfo.atc.fast = this.fast.version.version;
})
.catch(err => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
// debugger;
});
// check AS3 installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.as3.endPoints.info)
.then(resp => {
// if http 2xx, create as3 client
// notice the recast of resp.data type of "unknown" to "AtcInfo"
this.as3 = new as3Client_1.As3Client(resp.data, this.atcMetaData.as3, this.mgmtClient);
if (!returnInfo.atc) {
returnInfo.atc = {};
}
returnInfo.atc.as3 = this.as3.version.version;
})
.catch(err => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
// debugger;
});
// check DO installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.do.endPoints.info)
.then(resp => {
this.do = new doClient_1.DoClient(resp.data[0], this.atcMetaData.do, this.mgmtClient);
if (!returnInfo.atc) {
returnInfo.atc = {};
}
returnInfo.atc.do = this.do.version.version;
})
.catch(() => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
});
// check TS installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.ts.endPoints.info)
.then(resp => {
this.ts = new tsClient_1.TsClient(resp.data, this.atcMetaData.ts, this.mgmtClient);
if (!returnInfo.atc) {
returnInfo.atc = {};
}
returnInfo.atc.ts = this.ts.version.version;
})
.catch(() => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
});
// check CF installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.cf.endPoints.info)
.then(resp => {
this.cf = new cfClient_1.CfClient(resp.data, this.mgmtClient);
if (!returnInfo.atc) {
returnInfo.atc = {};
}
returnInfo.atc.cf = this.cf.version.version;
})
.catch(() => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
});
}
else if (this.mgmtClient instanceof nextClientBase_1.NextMgmtClient) {
// this is mbip, only discover things unique to mbip here...
// get swagger file from connected instance
// This file is 1-2Mb, we sure we want to do this EVERYTIME?
yield this.mgmtClient.makeRequest('/api/v1/openapi')
.then(resp => {
this.openApi = resp.data;
});
this.host = {}; // build the base object name to put all the mbip details
yield this.mgmtClient.makeRequest('/api/v1/systems')
.then(resp => this.host.systems = resp.data._embedded.systems);
this.host.hostname = this.host.systems[0].hostname;
this.host.machineId = this.host.systems[0].machineID;
yield this.mgmtClient.makeRequest('/api/v1/services')
.then(resp => this.host.services = resp.data._embedded.services);
yield this.mgmtClient.makeRequest('/api/v1/files')
.then(resp => this.host.files = resp.data._embedded.files);
yield this.mgmtClient.makeRequest('/api/v1/health')
.then(resp => this.host.health = resp.data._embedded.health);
// check FAST installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.fast.endPoints.info)
.then(resp => {
this.fast = new fastClient_1.FastClient(resp.data, this.atcMetaData.fast, this.mgmtClient);
returnInfo.atc = {};
returnInfo.atc.fast = this.fast.version.version;
})
.catch(err => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
});
// check AS3 installed by getting verion info
yield this.mgmtClient.makeRequest(this.atcMetaData.as3.endPoints.info)
.then(resp => {
// if http 2xx, create as3 client
// notice the recast of resp.data type of "unknown" to "AtcInfo"
this.as3 = new as3Client_1.As3Client(resp.data, this.atcMetaData.as3, this.mgmtClient);
if (!returnInfo.atc) {
returnInfo.atc = {};
}
returnInfo.atc.as3 = this.as3.version.version;
})
.catch(err => {
// do nothing... but catch the error from bubbling up and causing other issues
// this.logger.debug(err);
});
}
else if (this.mgmtClient instanceof nextCmClientBase_1.NextCmMgmtClient) {
// this is all NEXT-CM setup
yield this.mgmtClient.makeRequest('/api/openapi')
.then(resp => {
this.openApi = resp.data;
});
yield this.mgmtClient.makeRequest('/api/system/v1/info')
.then(resp => {
this.mgmtClient.hostInfo.version = resp.data.release_version;
this.mgmtClient.hostInfo.build = resp.data.build_number;
});
// assign details to this and mgmtClient class
this.mgmtClient.hostInfo.hostname = 'central-manager-hostname';
returnInfo.hostname = this.mgmtClient.hostInfo.hostname;
returnInfo.version = this.mgmtClient.hostInfo.version;
}
this.host = this.mgmtClient.hostInfo;
// return object of discovered services
return returnInfo;
});
}
/**
* upload file to f5 -> used for ucs/ilx-rpms/.conf-merges
*
* types of F5 uploads
* - FILE
* - uri: '/mgmt/shared/file-transfer/uploads'
* - path: '/var/config/rest/downloads'
* - ISO
* - uri: '/mgmt/cm/autodeploy/software-image-uploads'
* - path: '/shared/images'
*
* @param localSourcePathFilename
* @param uploadType
*/
upload(localSourcePathFilename, uploadType) {
return __awaiter(this, void 0, void 0, function* () {
return this.mgmtClient.upload(localSourcePathFilename, uploadType);
});
}
/**
* download file from f5 (ucs/qkview/iso)
* - UCS
* - uri: /mgmt/shared/file-transfer/ucs-downloads/${fileName}
* - path: /var/local/ucs/${fileName}
* - QKVIEW
* - uri: /mgmt/cm/autodeploy/qkview-downloads/${fileName}
* - path: /var/tmp/${fileName}
* - ISO
* - uri: /mgmt/cm/autodeploy/software-image-downloads/${fileName}
* - path: /shared/images/${fileName}
*
* @param fileName file name on bigip
* @param localDestPathFile where to put the file (including file name)
* @param downloadType: type F5DownLoad = "UCS" | "QKVIEW" | "ISO"
*/
download(fileName, localDestPath, downloadType) {
return __awaiter(this, void 0, void 0, function* () {
// todo: update response typeing to include http details
return this.mgmtClient.download(fileName, localDestPath, downloadType);
});
}
}
exports.F5Client = F5Client;
//# sourceMappingURL=f5Client.js.map