Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http-axios updates #3

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 61 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
// "resolveSourceMapLocations": [
// "${workspaceFolder}/**",
// "!/node_modules/**"
// ],
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Mocha MgmtClient tests",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"args": [
"-r",
"ts-node/register",
"--timeout",
"999999",
"--colors",
"${workspaceFolder}/tests/unit/bigip/managementClientTests.ts",
],
"internalConsoleOptions": "neverOpen",
"protocol": "inspector",
},
{
"type": "node",
"request": "launch",
"name": "Mocha ipv6 tests",
// "trace": true,
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"args": [
"-r",
"ts-node/register",
"--timeout",
"999999",
"--colors",
"${workspaceFolder}/tests/unit/ipv6.tests.ts",
],
"internalConsoleOptions": "neverOpen",
"protocol": "inspector",
},
{
"type": "node",
"request": "launch",
"name": "Mocha All",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"args": [
"-r",
"ts-node/register",
"--timeout",
"999999",
"--colors",
"${workspaceFolder}/tests/**/*.tests.ts",
],
"internalConsoleOptions": "neverOpen",
"protocol": "inspector",
}
]
}
100 changes: 100 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,108 @@ Benefits:
## Table of Contents

- [Usage](#usage)
- [Ben-Work](#ben-work)
- [User Documentation](#user-documentation)


---

## Ben Work

The high level goal here is to make an HTTP client that supports everything we need to take our tools to the next level.

### http-timer for axios requests

https://github.com/szmarczak/http-timer

The above plugin adds the following timings object to the response of axios
```typescript
export interface Timings {
start: number;
socket?: number;
lookup?: number;
connect?: number;
secureConnect?: number;
upload?: number;
response?: number;
end?: number;
error?: number;
abort?: number;
phases: {
wait?: number;
dns?: number;
tcp?: number;
tls?: number;
request?: number;
firstByte?: number;
download?: number;
total?: number;
};
}
```

### new HTTP Response type including the timings
```typescript
export type HttpResponse = {
data?: unknown;
headers?: unknown;
status: number;
statusText?: string;
request?: {
url: string;
method: string;
headers: unknown;
protocol: string;
timings: Timings;
// data?: unknown;
};
};
```

Using these timings we can log and provide stats about what devices (mainly f5) are responding slower than other or a gathered base line

### Upgrades!
- Full request timings: (DONE)
- See timing details above
- tests updated and working
- token timer (DONE)
- Read token TTL and utilize for entire lifetime of token
- refresh automatically as needed
- probably need to add more error handling, but this is a good start
- tests updated and working
- Added support for supplying remote authentication provider (DONE)
- If none is supplied, the default 'local' is set
- IPv6 support (DONE)
- Tests with basic usage/connectivity
- Added additional response details necessary for upper layer integration, like request details and full response details


### Further plans (mostly in priority...)
- layered functions that do all the work of uploading/downloadin files and capturing ucs/qkviews
- Expand ils rpm installs to monitor restjavad/restnoded processes to complete restart for job completion
- Currently only seems to make sure the install process completed, not that the services have restarted and are ready for processing again.
- This needs to be monitored so other processes are not trying to use the service while it's restarting. Depending on the host f5 config size and resources, this can take anywhere between 20 and 90 seconds.
- bigiq specific support
- confirm installing/uninstalling of ATC service (fast/as3/do/ts)
- has different api... :(
- confirm file upload/download
- confirm bigiq ucs/qkview generation
- service discovery
- can we get the necessary details from the same CDN network?
- Service discovery for ATC (maybe?)
- What services are installed
- Support both http and https connections (maybe?)
- When connecting to an F5 device only HTTPS will be used
- But there may be use cases where http is necessary for some sort of external connection
- May leave open the option for connecting over a linux socket also... (maybe?)
- Possible support for following redirects
- Should be part of axios client (just need to document how to use it)
- Support for failed auth events (probably not)
- This is to allow the packege to be consumed by any other service, like a command line tool, but also be able to integrate into the vscode extension to clear password cache when authentication fails
- Thinking more on this, it should probably be handled by whatever is utilizing the sdk

---

## Usage

Basic Example:
Expand Down
25 changes: 19 additions & 6 deletions package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
},
"scripts": {
"lint": "tsc --noEmit && eslint 'src/**/*.{js,ts,tsx}' 'tests/**/*.{js,ts,tsx}'",
"test": "nyc mocha -r ts-node/register \"tests/**/*Tests.ts\"",
"test": "nyc mocha -r ts-node/register \"tests/**/*.tests.ts\"",
"build-code-docs": "typedoc --out code_docs src",
"build-package": "tsc"
},
"dependencies": {
"@szmarczak/http-timer": "^4.0.5",
"axios": "^0.19.2"
},
"devDependencies": {
Expand Down
9 changes: 7 additions & 2 deletions src/bigip/extension/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const EXTENSION_METADATA = {
export class MetadataClient {
protected _component: string;
protected _componentVersion: string;
protected _metadata: object;
protected _metadata: unknown;

/**
*
Expand Down Expand Up @@ -147,7 +147,12 @@ export class MetadataClient {
*/
async getLatestMetadata(): Promise<void> {
const parsedUrl = httpUtils.parseUrl(EXTENSION_METADATA.url);
this._metadata = await httpUtils.makeRequest(parsedUrl.host, parsedUrl.path);
try {
const response = await httpUtils.makeRequest(parsedUrl.host, parsedUrl.path);
this._metadata = response.data;
} catch (e) {
console.log(e);
}
}

/**
Expand Down
24 changes: 12 additions & 12 deletions src/bigip/extension/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ export class PackageClient {
}> {
const queryResponse = await this._mgmtClient.makeRequest(PKG_MGMT_URI, {
method: 'POST',
body: {
data: {
operation: 'QUERY'
}
});
const response = await this._checkRpmTaskStatus(queryResponse['id']);
const response = await this._checkRpmTaskStatus(queryResponse['data']['id']);
// find matching packages
const matchingPackages = response['queryResponse'].filter(
const matchingPackages = response['data']['queryResponse'].filter(
(i: object) => componentPackageName == i['name']);
// now grab the matched package name, typically only one match
let packageName = null;
Expand All @@ -160,12 +160,12 @@ export class PackageClient {
while (i < maxCount) {
const response = await this._mgmtClient.makeRequest(`${PKG_MGMT_URI}/${taskId}`);

if (response['status'] === 'FINISHED') {
if (response['data']['status'] === 'FINISHED') {
return response;
} else if (response['status'] === 'FAILED') {
return Promise.reject(new Error(`RPM installation failed: ${response['errorMessage']}`));
} else if (response['data']['status'] === 'FAILED') {
return Promise.reject(new Error(`RPM installation failed: ${response['data']['errorMessage']}`));
} else if (i > maxCount) {
return Promise.reject(new Error(`Max count exceeded, last response: ${response['errorMessage']}`));
return Promise.reject(new Error(`Max count exceeded, last response: ${response['data']['errorMessage']}`));
}

i += 1;
Expand Down Expand Up @@ -200,27 +200,27 @@ export class PackageClient {
PKG_MGMT_URI,
{
method: 'POST',
body: {
data: {
operation: 'INSTALL',
packageFilePath: packagePath
}
}
);
await this._checkRpmTaskStatus(response['id']);
await this._checkRpmTaskStatus(response['data']['id']);
}

protected async _uninstallRpm(packageName: string): Promise<void> {
const response = await this._mgmtClient.makeRequest(
PKG_MGMT_URI,
{
method: 'POST',
body: {
data: {
operation: 'UNINSTALL',
packageName
}
}
);
await this._checkRpmTaskStatus(response['id']);
await this._checkRpmTaskStatus(response['data']['id']);
}

protected async _uploadRpm(file: string, options?: {
Expand All @@ -244,7 +244,7 @@ export class PackageClient {
'Content-Range': `${start}-${end}/${fileStats.size}`,
'Content-Length': end - start + 1
},
body: fs.createReadStream(file, { start, end }),
data: fs.createReadStream(file, { start, end }),
contentType: 'raw'
}
);
Expand Down