Compare commits
1 Commits
developmen
...
user/dvasi
Author | SHA1 | Date |
---|---|---|
Dimitrios Vasilas | eb72f28599 |
|
@ -102,5 +102,5 @@ dist
|
|||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
lib/
|
||||
lib/**
|
||||
openapi.yaml
|
||||
|
|
12
.swcrc
12
.swcrc
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"$schema": "https://swc.rs/schema.json",
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
},
|
||||
"target": "es2017"
|
||||
},
|
||||
"module": {
|
||||
"type": "commonjs"
|
||||
}
|
||||
}
|
44
README.md
44
README.md
|
@ -1,44 +0,0 @@
|
|||
# Scuba Client Library
|
||||
|
||||
This repository provides a client library for the Scuba service.
|
||||
The repository also provides a CLI binary to interact with the
|
||||
Scuba Service.
|
||||
|
||||
The supported operations are:
|
||||
|
||||
- Get the utilization metrics at a given time
|
||||
- Get the latest utilization metrics
|
||||
- Check the health of the Scuba service
|
||||
|
||||
## Contributing
|
||||
|
||||
In order to contribute, please follow the
|
||||
[Contributing Guidelines](
|
||||
https://github.com/scality/Guidelines/blob/master/CONTRIBUTING.md).
|
||||
|
||||
## Prerequisite
|
||||
|
||||
- Recommended Node version: >16.x.
|
||||
- Yarn must be installed to build the project.
|
||||
- An Open API yaml file defining the routes to use.
|
||||
|
||||
Node.js can be installed from [nodejs.org](https://nodejs.org/en/download/) and
|
||||
Yarn can be installed from [yarnpkg.com](https://yarnpkg.com/en/docs/install).
|
||||
|
||||
## Usage
|
||||
|
||||
To generate the client, run the following command:
|
||||
|
||||
```bash
|
||||
./bin/generate-client.sh
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
ScubaClient supports AWS Signature Version 4 authentication. To use this
|
||||
authentication method, you must have a set of credentials with permission
|
||||
to perform the desired operations.
|
||||
|
||||
### Command-Line Interface
|
||||
|
||||
Command-line support is not yet available.
|
14
package.json
14
package.json
|
@ -10,8 +10,9 @@
|
|||
"build": "tsc --strict",
|
||||
"lint": "prettier -c $(git ls-files '*.[jt]s') && eslint $(git ls-files '*.[jt]s')",
|
||||
"format": "prettier -w src && yarn lint --fix",
|
||||
"postprepare": "[ -d lib ] || swc -d lib --copy-files index.ts src",
|
||||
"prepack": "tsc --strict"
|
||||
"postinstall": "yarn build",
|
||||
"prepack": "yarn build",
|
||||
"prepare": "yarn build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.2",
|
||||
|
@ -26,22 +27,15 @@
|
|||
"eslint": "^8.28.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-scality": "git+https://git.yourcmc.ru/vitalif/zenko-eslint-config-scality.git",
|
||||
"eslint-config-scality": "git+https://github.com/scality/Guidelines#7.10.2",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"prettier": "^2.8.7",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"@smithy/signature-v4": "^2.1.1",
|
||||
"@swc/cli": "^0.4.0",
|
||||
"@swc/core": "^1.7.4",
|
||||
"axios": "^1.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
||||
|
|
54
src/api.ts
54
src/api.ts
|
@ -142,38 +142,6 @@ export const ScubaApiAxiosParamCreator = function (configuration?: Configuration
|
|||
};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration);
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
healthCheck: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = '/health/deep';
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options };
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
};
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
|
@ -236,16 +204,6 @@ export const ScubaApiFp = function (configuration?: Configuration) {
|
|||
);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async getHealthCheck(
|
||||
options?: AxiosRequestConfig,
|
||||
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.healthCheck(options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -335,16 +293,4 @@ export class ScubaApi extends BaseAPI {
|
|||
.getMetrics(metricsClass, resourceName, metricsDate, body, options)
|
||||
.then(request => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Health check endpoint
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof ScubaApi
|
||||
*/
|
||||
public healthCheck(options?: AxiosRequestConfig) {
|
||||
return ScubaApiFp(this.configuration)
|
||||
.getHealthCheck(options)
|
||||
.then(request => request(this.axios, this.basePath));
|
||||
}
|
||||
}
|
||||
|
|
101
src/client.ts
101
src/client.ts
|
@ -1,26 +1,12 @@
|
|||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
|
||||
import { SignatureV4 } from '@smithy/signature-v4';
|
||||
import globalAxios, { AxiosRequestConfig, AxiosInstance, AxiosHeaders } from 'axios';
|
||||
import { Sha256 } from '@aws-crypto/sha256-js';
|
||||
import { URL } from 'url';
|
||||
import { parse as parseQuerystring } from 'querystring';
|
||||
import { ScubaApi } from './api';
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
import { Configuration, ConfigurationParameters } from './configuration';
|
||||
import { ScubaApi } from './api';
|
||||
|
||||
export type MetricsClass = 'account' | 'bucket' | 'service';
|
||||
|
||||
type WithOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||
|
||||
export type SignatureParameter = WithOptional<
|
||||
ConstructorParameters<typeof SignatureV4>[0],
|
||||
'service' | 'region' | 'sha256'
|
||||
>;
|
||||
export type ScubaAuth = {
|
||||
awsV4?: SignatureParameter;
|
||||
};
|
||||
|
||||
export type ScubaClientParameters = Omit<
|
||||
ConfigurationParameters,
|
||||
'username' | 'password' | 'accessToken' | 'formDataCtor'
|
||||
|
@ -32,7 +18,6 @@ export type ScubaClientParameters = Omit<
|
|||
cert?: string;
|
||||
ca?: string;
|
||||
keepAlive?: boolean;
|
||||
auth?: ScubaAuth;
|
||||
};
|
||||
|
||||
export type ScubaMetrics = {
|
||||
|
@ -40,12 +25,6 @@ export type ScubaMetrics = {
|
|||
bytesTotal: number;
|
||||
metricsClass: string;
|
||||
resourceName: string;
|
||||
id?: number;
|
||||
date?: string;
|
||||
};
|
||||
|
||||
export type HealthCheckResponse = {
|
||||
date?: string;
|
||||
};
|
||||
|
||||
function lpad(num: number, digits: number) {
|
||||
|
@ -57,13 +36,8 @@ export default class ScubaClient {
|
|||
|
||||
private _defaultReqOptions: { httpAgent: http.Agent; httpsAgent: https.Agent };
|
||||
|
||||
private _axios: AxiosInstance;
|
||||
|
||||
/** Id of axios interceptor */
|
||||
private _authInterceptor: number | null = null;
|
||||
|
||||
constructor(params?: ScubaClientParameters) {
|
||||
const { basePath, host, port, useHttps, key, cert, ca, keepAlive, auth } = params || {};
|
||||
const { basePath, host, port, useHttps, key, cert, ca, keepAlive } = params || {};
|
||||
const proto = useHttps ? 'https' : 'http';
|
||||
const _host = host || 'localhost';
|
||||
const _port = port || 8100;
|
||||
|
@ -80,67 +54,16 @@ export default class ScubaClient {
|
|||
}),
|
||||
};
|
||||
|
||||
this._axios = globalAxios.create();
|
||||
|
||||
// If basePath is a FQDN then it overrides the baked in config from the spec
|
||||
this._api = new ScubaApi(new Configuration({ ...params, basePath: connectionString }), undefined, this._axios);
|
||||
|
||||
if (auth) {
|
||||
this.setAuth(auth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove current auth axios interceptor and add a new one
|
||||
* @param {ScubaAuth} auth Authentication method and options
|
||||
* @param {Aws4InterceptorParameter} [auth.awsV4] - parameters passed to aws4-axios
|
||||
* @return {undefined}
|
||||
*/
|
||||
setAuth(auth: ScubaAuth): void {
|
||||
if (this._authInterceptor !== null && this._authInterceptor !== undefined) {
|
||||
this._axios.interceptors.request.eject(this._authInterceptor);
|
||||
this._authInterceptor = null;
|
||||
}
|
||||
|
||||
if (auth.awsV4) {
|
||||
const signer = new SignatureV4({
|
||||
service: 's3',
|
||||
sha256: Sha256,
|
||||
region: 'us-east-1',
|
||||
...auth.awsV4,
|
||||
});
|
||||
|
||||
this._authInterceptor = this._axios.interceptors.request.use(async req => {
|
||||
const { host, hostname, pathname, protocol, search } = new URL(this._axios.getUri(req));
|
||||
// remove first char '?' from qs
|
||||
const query = parseQuerystring(search?.substring(1)) as Record<string, string | string[]>;
|
||||
|
||||
const requestToSign = {
|
||||
method: req.method?.toUpperCase()!,
|
||||
headers: { host, ...(req.headers as Record<string, any>) },
|
||||
body: req.data,
|
||||
host,
|
||||
hostname,
|
||||
path: pathname,
|
||||
protocol,
|
||||
query,
|
||||
};
|
||||
const res = await signer.sign(requestToSign);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
req.headers = new AxiosHeaders(res.headers);
|
||||
return req;
|
||||
});
|
||||
}
|
||||
this._api = new ScubaApi(new Configuration({ ...params, basePath: connectionString }));
|
||||
}
|
||||
|
||||
async getLatestMetrics(
|
||||
metricsClass: MetricsClass,
|
||||
resourceName: string,
|
||||
options?: AxiosRequestConfig,
|
||||
body?: any,
|
||||
): Promise<ScubaMetrics> {
|
||||
const resp = (await this._api.getLatestMetrics(metricsClass, resourceName, body, {
|
||||
const resp = (await this._api.getLatestMetrics(metricsClass, resourceName, undefined, {
|
||||
...this._defaultReqOptions,
|
||||
...options,
|
||||
})) as any;
|
||||
|
@ -152,21 +75,15 @@ export default class ScubaClient {
|
|||
resourceName: string,
|
||||
date: Date,
|
||||
options?: AxiosRequestConfig,
|
||||
body?: any,
|
||||
): Promise<ScubaMetrics> {
|
||||
const year = lpad(date.getUTCFullYear(), 4);
|
||||
const month = lpad(date.getUTCMonth() + 1, 2);
|
||||
const day = lpad(date.getUTCDate(), 2);
|
||||
const year = lpad(date.getFullYear(), 4);
|
||||
const month = lpad(date.getMonth(), 2);
|
||||
const day = lpad(date.getDate(), 2);
|
||||
const dateString = `${year}-${month}-${day}`;
|
||||
const resp = (await this._api.getMetrics(metricsClass, resourceName, dateString, body, {
|
||||
const resp = (await this._api.getMetrics(metricsClass, resourceName, dateString, undefined, {
|
||||
...this._defaultReqOptions,
|
||||
...options,
|
||||
})) as any;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
async healthCheck(options?: AxiosRequestConfig): Promise<HealthCheckResponse> {
|
||||
const resp = (await this._api.healthCheck({ ...this._defaultReqOptions, ...options })) as any;
|
||||
return resp.data;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue