Skip to content

Commit

Permalink
new SDK and command line tool
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagobustamante committed May 12, 2017
1 parent 9d273a1 commit e64c632
Show file tree
Hide file tree
Showing 15 changed files with 327 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ dist
node_modules
.npm
doc
test/data/root/middleware
test/data/root/logs
/middleware
/.vscode
coverage
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"passport-local": "^1.0.0",
"path-to-regexp": "^1.6.0",
"serve-favicon": "~2.3.0",
"swagger-client": "^3.0.9",
"typescript-ioc": "^0.4.0",
"typescript-rest": "^1.0.1",
"typescript-rest-swagger": "^0.0.4",
Expand Down Expand Up @@ -126,7 +127,8 @@
},
"bin": {
"treeGateway": "dist/app-cluster.js",
"userAdmin": "dist/admin/user/user-admin.js"
"userAdmin": "dist/admin/user/user-admin.js",
"treeGatewayConfig": "dist/admin/config/cli.js"
},
"bugs": {
"url": "https://github.com/Leanty/tree-gateway/issues"
Expand Down
11 changes: 7 additions & 4 deletions src/admin/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
'use strict';

import { Path, GET, POST, DELETE, PUT, PathParam, Errors, Return } from 'typescript-rest';
import { Path, GET, POST, DELETE, PUT, PathParam, QueryParam, Errors, Return } from 'typescript-rest';
import { ApiConfig, validateApiConfig } from '../../config/api';
import { ApiService } from '../../service/api';
import { Inject } from 'typescript-ioc';
import * as swagger from 'typescript-rest-swagger';

@Path('apis')
@swagger.Tags('APIs administration')
@swagger.Tags('APIs')
@swagger.Security('Bearer')
export class APIRest {
@Inject private service: ApiService;

@GET
list(): Promise<Array<ApiConfig>> {
return this.service.list();
list(@QueryParam('name')name?: string,
@QueryParam('version')version?: string,
@QueryParam('description')description?: string,
@QueryParam('path')path?: string): Promise<Array<ApiConfig>> {
return this.service.list(name, version, description, path);
}

@POST
Expand Down
2 changes: 1 addition & 1 deletion src/admin/api/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Inject } from 'typescript-ioc';
import * as swagger from 'typescript-rest-swagger';

@Path('gateway')
@swagger.Tags('Gateway Configuration')
@swagger.Tags('Gateway')
@swagger.Security('Bearer')
export class GatewayRest {
@Inject private service: GatewayService;
Expand Down
2 changes: 1 addition & 1 deletion src/admin/api/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Inject } from 'typescript-ioc';
import * as swagger from 'typescript-rest-swagger';

@Path('middleware')
@swagger.Tags('Middleware Configurations')
@swagger.Tags('Middleware')
@swagger.Security('Bearer')
export class MiddlewareRest {
@Inject private service: MiddlewareService;
Expand Down
2 changes: 1 addition & 1 deletion src/admin/api/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { StatsRecorder } from '../../stats/stats-recorder';
import * as swagger from 'typescript-rest-swagger';

@Path('stats')
@swagger.Tags('Stats Monitoring')
@swagger.Tags('Stats')
@swagger.Security('Bearer')
export class StatsRest {
@Inject private monitors: Monitors;
Expand Down
2 changes: 1 addition & 1 deletion src/admin/api/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Container, Inject } from 'typescript-ioc';
import * as swagger from 'typescript-rest-swagger';

@Path('users')
@swagger.Tags('Users Management')
@swagger.Tags('Users')
export class UsersRest {
@Inject private service: UserService;

Expand Down
66 changes: 66 additions & 0 deletions src/admin/config/cli-args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';

import { ArgumentParser } from 'argparse';

const parser = new ArgumentParser({
addHelp: true,
description: 'Tree-Gateway Admin',
version: '0.0.1'
});

parser.addArgument(['-s', '--swagger'], {
help: 'Inform the URL pointing to the swagger file on the Tree Gateway target server',
required: true
});

parser.addArgument(['-u', '--username'], {
help: 'Inform the user to sign in into the gateway API',
required: true
});

parser.addArgument(['-p', '--password'], {
help: 'Inform the user password to sign in into the gateway API',
required: true
});

const commands = parser.addSubparsers({
dest: 'command',
title: 'Commands (For help, <command> -h/--help)'
});

const apisCommand = commands.addParser('apis', {
addHelp: true,
help: 'APIs configurations'
});

apisCommand.addArgument(
['-l', '--list'], {
help: 'Inform the search params for API listing. Ex: name:test|version:0.0.1'
}
);

apisCommand.addArgument(
['-a', '--add'], {
help: 'Inform the path to the api config file (JSON format) to be added',
}
);

apisCommand.addArgument(
['-u', '--update'], {
help: 'Inform the path to the api config file (JSON format) to be updated',
}
);

apisCommand.addArgument(
['-r', '--remove'], {
help: 'Inform the path to the api config file (JSON format) to be removed',
}
);

apisCommand.addArgument(
['-g', '--get'], {
help: 'Inform the path to the api config file (JSON format) to be retrieved',
}
);

export let configArgs = parser.parseArgs();
82 changes: 82 additions & 0 deletions src/admin/config/cli-tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

import {SDK} from './sdk';
import { ApiConfig } from '../../config/api';
import * as fs from 'fs-extra-promise';

export class Cli {
private args: any;

constructor(configArgs: any) {
this.args = configArgs;
}

processCommand() {
this.doCommand()
.then(() => {
console.info(`Command ${this.args.command} completed.`);
}).catch((err: any) => {
console.error(`${err}`);
process.exit(1);
});
}

private doCommand(): Promise<void> {
switch (this.args.command) {
case 'apis':
return this.processApis();
default:
return new Promise<void>((resolve, reject) => reject(`Command not found: ${this.args.command}`));
}
}

private processApis(): Promise<void> {
return new Promise<void>((resolve, reject) => {
SDK.initialize(this.args.swagger, this.args.username, this.args.password)
.then((sdk: SDK) => {
if (this.args.list) {
const args: any = {};
const params = this.args.list.split('\\|');
params.forEach((param: string) => {
const parts = param.split(':');
if (parts.length !== 2) {
throw new Error(`Invalid arguments for list command: ${this.args.list}`);
}
args[parts[0]] = parts[1];
});
sdk.apis.list(args)
.then(apis => {
console.info(JSON.stringify(apis));
})
.catch(reject);
} else if (this.args.add) {
fs.readJSONAsync(this.args.add)
.then((api: ApiConfig) => sdk.apis.addApi(api))
.then(apiId => {
console.info(`API created. ID: ${apiId}`);
})
.catch(reject);
} else if (this.args.update) {
fs.readJSONAsync(this.args.update)
.then((api: ApiConfig) => sdk.apis.updateApi(api.id, api))
.then(() => {
console.info(`API updated`);
})
.catch(reject);
} else if (this.args.remove) {
sdk.apis.deleteApi(this.args.remove)
.then(() => {
console.info(`API removed`);
})
.catch(reject);
} else if (this.args.get) {
sdk.apis.getApi(this.args.get)
.then(api => {
console.info(JSON.stringify(api));
})
.catch(reject);
}
});
});
}
}
11 changes: 11 additions & 0 deletions src/admin/config/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env node
'use strict';

import { configArgs } from './cli-args';
import { Cli } from './cli-tool';

try {
new Cli(configArgs).processCommand();
} catch (e) {
console.error(e);
}
128 changes: 128 additions & 0 deletions src/admin/config/sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
'use strict';

import { ApiConfig } from '../../config/api';

const swagger = require('swagger-client');

export interface Apis {
list(filters: any): Promise<Array<ApiConfig>>;
addApi(api: ApiConfig): Promise<string>;
updateApi( id: string, api: ApiConfig): Promise<void>;
deleteApi( id: string): Promise<void>;
getApi( id: string): Promise<ApiConfig>;
}

export class SDK {
private apisClient: ApisClient;

private constructor(swaggerClient: any) {
this.apisClient = new ApisClient(swaggerClient);
}

static initialize(swaggerUrl: string, login: string, password: string): Promise<SDK> {
return new Promise<SDK>((resolve, reject) => {
SDK.authenticate(swaggerUrl, login, password)
.then(token => swagger(swaggerUrl, {
authorizations: {
Bearer: `JWT ${token}`
}
}))
.then((swaggerClient: any) => {
resolve(new SDK(swaggerClient));
})
.catch(reject);
});
}

static authenticate(swaggerUrl: string, login: string, password: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
swagger(swaggerUrl)
.then((swaggerClient: any) => swaggerClient.apis.Users.UsersRestGetAuthToken({login, password}))
.then((response: any) => {
if (response.status === 200) {
return resolve(response.text);
}
reject(response.text);
})
.catch(reject);
});
}

get apis(): Apis {
return this.apisClient;
}
}

class ApisClient implements Apis {
private swaggerClient: any;

constructor(swaggerClient: any) {
this.swaggerClient = swaggerClient;
}

list(filters: any): Promise<Array<ApiConfig>> {
return new Promise<Array<ApiConfig>>((resolve, reject) => {
this.swaggerClient.apis.APIs.APIRestList(filters)
.then((response: any) => {
if (response.status === 200) {
return resolve(response.body);
}
reject(response.text);
})
.catch(reject);
});
}

addApi(api: ApiConfig): Promise<string> {
return new Promise<string>((resolve, reject) => {
this.swaggerClient.apis.APIs.APIRestAddApi({api})
.then((response: any) => {
if (response.status === 201) {
return resolve(response.headers['Location'].substring(5));
}
reject(response.text);
})
.catch(reject);
});
}

updateApi( id: string, api: ApiConfig): Promise<void> {
return new Promise<void>((resolve, reject) => {
api.id = id;
this.swaggerClient.apis.APIs.APIRestUpdateApi({id, api})
.then((response: any) => {
if (response.status === 204) {
return resolve();
}
reject(response.text);
})
.catch(reject);
});
}

deleteApi( id: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
this.swaggerClient.apis.APIs.APIRestDeleteApi({id})
.then((response: any) => {
if (response.status === 204) {
return resolve();
}
reject(response.text);
})
.catch(reject);
});
}

getApi( id: string): Promise<ApiConfig> {
return new Promise<ApiConfig>((resolve, reject) => {
this.swaggerClient.apis.APIs.APIRestGetApi({id})
.then((response: any) => {
if (response.status === 200) {
return resolve(response.body);
}
reject(response.text);
})
.catch(reject);
});
}
}
2 changes: 1 addition & 1 deletion src/admin/user/user-admin-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class UserAdmin {
.then(() => {
console.info(`Command ${this.args.command} completed.`);
this.closeDB();
}).catch(err => {
}).catch((err: any) => {
console.error(`${err}`);
process.exit(1);
});
Expand Down

0 comments on commit e64c632

Please sign in to comment.