Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5,664 changes: 5,664 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

94 changes: 23 additions & 71 deletions src/App.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,40 @@
import {inArray, loadEnvVariablesFromFile} from './Helpers';
import {loadEnvVariablesFromFile} from './Helpers';
import {UpgradeModule} from './Modules/UpgradeModule';
import {ProcessHelper} from './ProcessHelper';
import {ConfigFactory} from './Config/app-config';
import {HelmProxyModule} from './Modules/HelmProxyModule';
import {VersionModule} from './Modules/VersionModule';
import * as console from 'console';
import {hideBin} from 'yargs/helpers';
import * as yargs from 'yargs';
import * as process from 'process';
import {Container} from './Core/Container';
import {Application} from './Core/Application';
import {CliParser} from './Cli/CliParser';
import {ConfigFactory} from './Config/app-config';
import {IConfigProvider} from './Types';

loadEnvVariablesFromFile();

const processHelper = new ProcessHelper();
const upgradeModule = new UpgradeModule();
const helmProxyModule = new HelmProxyModule();
const versionModule = new VersionModule();
const container = new Container();

processHelper.setExitHandler((data: { code: string }) => {
process.emit('message', '', '');
(async () => {
if (!inArray(['exit'], data.code)) {
console.log('[helm-assistant] Stop signal received ', [data.code]);
}
console.log('[helm-assistant] Graceful stop all modules');
await Promise.all([upgradeModule, helmProxyModule].map((item: any) => {
return item.stop();
})).catch((error) => {
console.log('[helm-assistant] Can not stop services', error);
// process.exitCode = 1;
});
console.log('[helm-assistant] System gracefully stopped');
})();
});
processHelper.subscribeOnProcessExit();
container.registerSingleton<IConfigProvider>('config', () => ConfigFactory.getInstance());

(async () => {
const app = new Application(container);

let HELM_CMD_ARGS = ConfigFactory.getCore().HELM_CMD_ARGS;
if (ConfigFactory.getCore().HELM_DEBUG === true) {
HELM_CMD_ARGS += ' --debug';
}
if (ConfigFactory.getCore().HELM_DRY_RUN === true) {
HELM_CMD_ARGS += ' --dry-run';
}
const argv:any = yargs(hideBin(process.argv))
.version(false)
.option('wait', {type: 'boolean'})
.option('wait-for-jobs', {type: 'boolean'})
.option('atomic', {type: 'boolean'})
.option('debug', {type: 'boolean'})
.option('dry-run', {type: 'boolean'})
.option('install', {type: 'boolean'})
.option('cleanup-on-fail', {type: 'boolean'})
.option('create-namespace', {type: 'boolean'})
.option('devel', {type: 'boolean'})
.option('disable-openapi-validation', {type: 'boolean'})
.option('force', {type: 'boolean'})
.option('insecure-skip-tls-verify', {type: 'boolean'})
.option('no-hooks', {type: 'boolean'})
.option('reset-values', {type: 'boolean'})
.option('reuse-values', {type: 'boolean'})
.option('skip-crds', {type: 'boolean'})
.option('verify', {type: 'boolean'})
.option('verify', {type: 'boolean'})
.option('version', {type: 'string'})
.parse();
app.registerModule('upgrade', new UpgradeModule());
app.registerModule('helm-proxy', new HelmProxyModule());
app.registerModule('version', new VersionModule());

app.bootstrap();

const mode: string = argv._[0];
switch (mode) {
(async () => {
const cliParser = new CliParser();
const args = cliParser.parse();

switch (args.command) {
case 'upgrade':
await upgradeModule.run(argv);
await app.runModule('upgrade', args);
break;
case 'version':
await versionModule.run(argv);
await app.runModule('version', args);
break;
}


await helmProxyModule.runHelmCMD(ConfigFactory.getCore().HELM_BIN_PATH, [
...HELM_CMD_ARGS.split(' '),
...process.argv.slice(2)
]);
processHelper.exitHandler({code: 'exit'});

await app.runModule('helm-proxy', args);
app.triggerExit();
})();


50 changes: 50 additions & 0 deletions src/Cli/CliParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ParsedCliArgs } from '../Types';
import { hideBin } from 'yargs/helpers';
import * as yargs from 'yargs';
import * as process from 'process';

export class CliParser {

public parse(): ParsedCliArgs {
const argv: any = yargs(hideBin(process.argv))
.version(false)
.option('wait', {type: 'boolean'})
.option('wait-for-jobs', {type: 'boolean'})
.option('atomic', {type: 'boolean'})
.option('debug', {type: 'boolean'})
.option('dry-run', {type: 'boolean'})
.option('install', {type: 'boolean'})
.option('cleanup-on-fail', {type: 'boolean'})
.option('create-namespace', {type: 'boolean'})
.option('devel', {type: 'boolean'})
.option('disable-openapi-validation', {type: 'boolean'})
.option('force', {type: 'boolean'})
.option('insecure-skip-tls-verify', {type: 'boolean'})
.option('no-hooks', {type: 'boolean'})
.option('reset-values', {type: 'boolean'})
.option('reuse-values', {type: 'boolean'})
.option('skip-crds', {type: 'boolean'})
.option('verify', {type: 'boolean'})
.option('version', {type: 'string'})
.parse();

const command: string = argv._[0] || '';
const releaseName: string = argv._[1] || '';

let namespace: string = 'default';
if (typeof argv.namespace !== 'undefined') {
namespace = argv.namespace;
} else if (typeof argv.n !== 'undefined') {
namespace = argv.n;
}

return {
command,
releaseName,
namespace,
waitForJobs: argv.waitForJobs || false,
rawArgs: process.argv.slice(2),
...argv,
};
}
}
52 changes: 17 additions & 35 deletions src/Components/Logger.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,20 @@
import {ConfigFactory} from '../Config/app-config';
import {ILogger, ILoggerFactory, LogLevel} from '../Types';
import * as console from 'console';
import * as process from 'process';
import {inArray} from '../Helpers';

export default class Logger {
private static instance: Logger;
export default class Logger implements ILogger {
private readonly category: string;

/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
private constructor(category: string) {
this.category = category;
}

/**
* The static method that controls the access to the singleton instance.
*
* This implementation let you subclass the Singleton class while keeping
* just one instance of each subclass around.
*/
public static getInstance(category: string = ''): Logger {
return new Logger(category);
}

/**
* Finally, any singleton should define some business logic, which can be
* executed on its instance.
*/
public static trace(category: string, text: string, someData: object = {}) {
public static trace(category: string, text: string, someData: object = {}) {
Logger.getInstance(category).trace(text, someData);
}
public static info(category: string, text: string, someData: object = {}) {
Expand All @@ -50,11 +35,6 @@ export default class Logger {
Logger.getInstance(category).fatal(text, someData);
}


/**
* Finally, any singleton should define some business logic, which can be
* executed on its instance.
*/
public trace(text: string, someData: object = {}) {
this.log('trace', text, someData);
}
Expand All @@ -63,21 +43,21 @@ export default class Logger {
this.log('info', text, someData);
}

public debug(text: string, someData: object) {
public debug(text: string, someData: object = {}) {
this.log('debug', text, someData);
}
public warn(text: string, someData: object) {
public warn(text: string, someData: object = {}) {
this.log('warn', text, someData);
}
public error(text: string, someData: object) {
public error(text: string, someData: object = {}) {
this.log('error', text, someData);
}

public fatal(text: string, someData: object) {
public fatal(text: string, someData: object = {}) {
this.log('fatal', text, someData);
}

private log(level:string, text: string, someData: object) {
private log(level: LogLevel, text: string, someData: object) {
switch (ConfigFactory.getCore().LOGGER_DRIVER) {
case 'console':
this.logWithConsole(level, text, someData);
Expand All @@ -86,27 +66,25 @@ export default class Logger {
this.logWithDebug(level, text, someData);
break;
default:
console.error('Logger configuration filed. Unknown driver:' + ConfigFactory.getCore().LOGGER_DRIVER);
console.error('Logger configuration failed. Unknown driver:' + ConfigFactory.getCore().LOGGER_DRIVER);
return;
}
}
private logWithDebug(level:string, text: string, someData: object) {
private logWithDebug(level: LogLevel, text: string, someData: object) {
const log2 = require('debug')('[' + ConfigFactory.getBase().id + '][' + this.category + '][' + level + ']');
// log2.color = 'w';
// const log2 = logDebugger();
if (Object.entries(someData).length !== 0) {
log2( text + ' ' + JSON.stringify(someData));
} else {
log2(text);
}
}

private logWithConsole(level:string, text: string, someData: object) {
private logWithConsole(level: LogLevel, text: string, someData: object) {
if (inArray(['trace', 'debug'], level)) {
return;
}

let outputer;
let outputer: Function;
if (inArray(['fatal', 'error'], level)) {
outputer = console.error;
} else {
Expand All @@ -117,7 +95,11 @@ export default class Logger {
} else {
outputer('[' + ConfigFactory.getBase().id + '][' + this.category + '][' + level + '] ' + text);
}
}
}


export class LoggerFactory implements ILoggerFactory {
public create(category: string): ILogger {
return Logger.getInstance(category);
}
}
25 changes: 9 additions & 16 deletions src/Components/ProcessLocker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import * as fs from 'fs';
import { ConfigFactory } from '../Config/app-config';
import * as console from 'console';
// import { NodeJS } from 'timers';
import { IProcessLocker, ProcessLockerOptions } from '../Types';

export default class ProcessLocker {

private driver: 'fs' | 'redis';
export default class ProcessLocker implements IProcessLocker {

public options: ProcessLockerOptions;

Expand All @@ -18,11 +15,12 @@ export default class ProcessLocker {
fsDirPath: ConfigFactory.getCore().HELM_ASSISTANT_RELEASE_LOCK_FS_DIR_PATH
};
}

public async getLock(resource: string): Promise<boolean> {
await this.initFSLocker();
return await this.waitAvailability(resource);

}

public clearLock(resource: string): Promise<any> {
return new Promise(function(resolve, reject) {
if (fs.existsSync(this.options.fsDirPath + '/' + resource + '.lock')) {
Expand All @@ -44,12 +42,12 @@ export default class ProcessLocker {
}.bind(this));
}

private initFSLocker(): Promise<any> {
const res = fs.mkdirSync(this.options.fsDirPath, {recursive: true});
private initFSLocker(): Promise<void> {
fs.mkdirSync(this.options.fsDirPath, {recursive: true});
return Promise.resolve();
}

private async waitAvailability(key:string): Promise<boolean> {
private async waitAvailability(key: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
process.stdout.write('[helm-assistant][release-locker] NOTICE: Waiting for lock on: ' + this.options.fsDirPath + '/' + key + '.lock' + '\n');
this.timer = setInterval(() => {
Expand All @@ -75,12 +73,13 @@ export default class ProcessLocker {
});
}

private getLockData(key: string): string | false {
private getLockData(key: string): string | false {
if (fs.existsSync(this.options.fsDirPath + '/' + key + '.lock')) {
return fs.readFileSync(this.options.fsDirPath + '/' + key + '.lock', 'utf8');
}
return false;
}

private putLockData(key: string): Promise<boolean> {
const date = new Date();
date.setSeconds(date.getSeconds() + this.options.maxRetries);
Expand All @@ -96,10 +95,4 @@ export default class ProcessLocker {
}.bind(this));
}.bind(this));
}

}
interface ProcessLockerOptions {
maxRetries: number;
driver: string;
fsDirPath: string;
}
Loading
Loading