Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Merge 4889a4b into 540e47d
Browse files Browse the repository at this point in the history
  • Loading branch information
yiyione committed Jul 9, 2020
2 parents 540e47d + 4889a4b commit c48a6a6
Show file tree
Hide file tree
Showing 14 changed files with 1,174 additions and 216 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/code_coverage.yml
@@ -0,0 +1,36 @@
name: Code coverage

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: windows-latest

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2

- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x

- run: yarn install
- run: yarn test

- name: Coveralls GitHub Action
uses: coverallsapp/github-action@v1.1.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Path to lcov file
path-to-lcov: ./coverage/lcov.info
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -6,3 +6,5 @@ node_modules
!.vscode/
.vscode/extensions.json
.vscode/settings.json
.nyc_output
coverage
1 change: 1 addition & 0 deletions README.md
@@ -1,6 +1,7 @@
# OpenPAI VS Code Client

[![Version](https://img.shields.io/github/release/Microsoft/openpaivscode.svg)](https://github.com/Microsoft/openpaivscode/releases/latest)
[![Coverage Status](https://coveralls.io/repos/github/microsoft/openpaivscode/badge.svg?branch=master)](https://coveralls.io/github/microsoft/openpaivscode?branch=master)

[简体中文](https://github.com/microsoft/openpaivscode/blob/master/README_zh_CN.md)

Expand Down
22 changes: 19 additions & 3 deletions package.json
Expand Up @@ -625,7 +625,8 @@
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"package": "vsce package --yarn",
"test": "yarn compile && node ./installYamlExtension.js && node ./out/test/runTest.js"
"pretest": "yarn compile && node ./installYamlExtension.js",
"test": "nyc node ./node_modules/vscode/bin/test"
},
"devDependencies": {
"@types/fs-extra": "^5.0.4",
Expand All @@ -645,14 +646,17 @@
"@types/sshpk": "^1.10.4",
"@types/uuid": "^3.4.4",
"@types/vscode": "^1.40.0",
"istanbul-lib-coverage": "^3.0.0",
"mocha": "^7.1.1",
"nock": "^11.8.2",
"nyc": "^15.1.0",
"tslint": "^6.0.0",
"tslint-microsoft-contrib": "^5.2.1",
"typescript": "^3.5.1",
"typescript-tslint-plugin": "^0.4.0",
"vsce": "^1.74.0",
"vscode-test": "^1.3.0"
"vscode": "^1.1.37",
"vscode-test": "^1.4.0"
},
"dependencies": {
"@azure/storage-blob": "^12.0.1",
Expand All @@ -671,7 +675,7 @@
"node-rsa": "^1.0.7",
"node-yaml-parser": "^0.0.9",
"opn": "^5.4.0",
"reflect-metadata": "^0.1.12",
"reflect-metadata": "^0.1.13",
"request": "^2.88.0",
"request-promise-native": "^1.0.8",
"semver-compare": "^1.0.0",
Expand All @@ -681,5 +685,17 @@
"unzipper": "^0.10.1",
"uuid": "^3.3.2",
"webhdfs": "^1.2.0"
},
"nyc": {
"exclude": [
".vscode-test",
"src/test"
],
"reporter": [
"lcov",
"text",
"text-summary"
],
"all": true
}
}
22 changes: 11 additions & 11 deletions src/common/singleton.ts
Expand Up @@ -5,7 +5,7 @@
*/

import 'reflect-metadata'; // tslint:disable-line
import { injectable, Container } from 'inversify'; // tslint:disable-line
import { Container, injectable } from 'inversify'; // tslint:disable-line
import * as vscode from 'vscode';

import { __ } from './i18n';
Expand Down Expand Up @@ -57,20 +57,20 @@ export function getSingleton<T extends Singleton>(clazz: Constructor<T>): Promis
}

export function bindExtensionContext(context: vscode.ExtensionContext): void {
if (container.isBound(EXTENSION_CONTEXT)) {
container.unbind(EXTENSION_CONTEXT);
}

container.bind(EXTENSION_CONTEXT).toConstantValue(context);
}

export async function initializeAll(singletonClasses: Constructor<Singleton>[]): Promise<void> {
getSingletonDisabled = true;
const allSingletons: Singleton[] = singletonClasses.map(clazz => container.get(clazz));
getSingletonDisabled = false;
await Promise.all(allSingletons.map(singleton => singleton.ensureActivated()));
initializationFinish = true;
}

export async function waitForAllSingletonFinish(): Promise<void> {
while (!initializationFinish) {
await delay(10);
if (!initializationFinish) {
getSingletonDisabled = true;
const allSingletons: Singleton[] = singletonClasses.map(clazz => container.get(clazz));
getSingletonDisabled = false;
await Promise.all(allSingletons.map(singleton => singleton.ensureActivated()));
initializationFinish = true;
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/pai/clusterManager.ts
Expand Up @@ -8,6 +8,7 @@ import { PAIV2 } from '@microsoft/openpai-js-sdk';
import { injectable } from 'inversify';
import { clone, range } from 'lodash';
import * as request from 'request-promise-native';
import semverCompare = require('semver-compare'); // tslint:disable-line
import * as vscode from 'vscode';

import {
Expand All @@ -17,10 +18,8 @@ import { getSingleton, Singleton } from '../common/singleton';
import { Util } from '../common/util';

import { ClusterExplorerChildNode, ConfigurationTreeDataProvider, ITreeData } from './container/configurationTreeDataProvider';
import { IPAICluster } from './utility/paiInterface';

import semverCompare = require('semver-compare'); // tslint:disable-line
import { login } from './utility/azureADLogin';
import { IPAICluster } from './utility/paiInterface';

export interface IConfiguration {
readonly version: string;
Expand Down Expand Up @@ -66,14 +65,14 @@ export class ClusterManager extends Singleton {
protocol_version: '2'
};

public configuration: IConfiguration | undefined;

private onDidChangeEmitter: vscode.EventEmitter<IClusterModification> = new vscode.EventEmitter<IClusterModification>();
public onDidChange: vscode.Event<IClusterModification> = this.onDidChangeEmitter.event; // tslint:disable-line

private readonly EDIT: string = __('common.edit');
private readonly DISCARD: string = __('cluster.activate.fix.discard');

private configuration: IConfiguration | undefined;

public get allConfigurations(): IPAICluster[] {
return this.configuration!.pais;
}
Expand Down
9 changes: 8 additions & 1 deletion src/pai/storage/hdfs.ts
Expand Up @@ -34,6 +34,8 @@ import { IPAICluster } from '../utility/paiInterface';

import { createWebHDFSClient, IHDFSClient, IHDFSStatResult } from './webhdfs-workaround';

type Constructor<T> = new(...arg: any[]) => T;

const stat: (path: string) => Promise<fs.Stats> = promisify(fs.stat);
const readdir: (path: string) => Promise<string[]> = promisify(fs.readdir);
const mkdir: (path: string) => Promise<void> = fs.mkdirp;
Expand All @@ -52,6 +54,11 @@ export class HDFSFileSystemProvider implements vscode.FileSystemProvider {
public onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]> = this.onDidChangeFileEmitter.event; // tslint:disable-line

private clientMap: Map<string, IHDFSClient> = new Map();
private getSingleton: <T extends Singleton>(clazz: Constructor<T>) => T | Promise<T>;

constructor(getSingletonFunc?: <T extends Singleton>(clazz: Constructor<T>) => T | Promise<T>) {
this.getSingleton = getSingletonFunc || getSingleton;
}

// `${username}@${host}:${port}` (e.g. user@127.0.0.1:50070) as authority
public async addClient(authority: string): Promise<IHDFSClient | undefined> {
Expand All @@ -60,7 +67,7 @@ export class HDFSFileSystemProvider implements vscode.FileSystemProvider {
}
const [user, uri] = authority.split('@');
const [host, port = '80'] = uri.split(':');
const allConfigurations: IPAICluster[] = (await getSingleton(ClusterManager)).allConfigurations;
const allConfigurations: IPAICluster[] = (await this.getSingleton(ClusterManager)).allConfigurations;
const currentCluster: IPAICluster | undefined = allConfigurations.find(cluster =>
!!(cluster.username === user && cluster.webhdfs_uri && cluster.webhdfs_uri.startsWith(uri + '/'))
);
Expand Down
62 changes: 41 additions & 21 deletions src/test/clusterConfiguration.test.ts
Expand Up @@ -3,10 +3,11 @@
* Licensed under the MIT License. See License in the project root for license information.
* @author Microsoft
*/
// tslint:disable:align
import * as assert from 'assert';
import * as path from 'path';

import { getSingleton, waitForAllSingletonFinish } from '../common/singleton';
import { bindExtensionContext } from '../common/singleton';
import { UtilClass } from '../common/util';
import { ClusterManager } from '../pai/clusterManager';

async function asyncAssertThrows(fn: (...args: any[]) => Promise<any>, message: string): Promise<void> {
Expand All @@ -19,33 +20,52 @@ async function asyncAssertThrows(fn: (...args: any[]) => Promise<any>, message:
async function asyncAssertDoesNotThrow(fn: (...args: any[]) => Promise<any>, message: string): Promise<void> {
try {
await fn();
} catch {
} catch (err) {
console.log(`ERROR: ${err.message}`);
assert.fail(message);
}
}

suite('PAI Cluster Configurations', () => {
test('Configuration Validation', async () => {
await waitForAllSingletonFinish();
const clusterManager: ClusterManager = await getSingleton(ClusterManager);
clusterManager.allConfigurations[0] = <any>{};
await asyncAssertThrows(async () => {
await clusterManager.validateConfiguration();
}, 'Invalid configuration should not pass validation');
bindExtensionContext(<any>{
extensionPath: path.resolve(__dirname, '../../'),
subscriptions: []
});
// tslint:disable-next-line: no-unused-expression
new UtilClass();
let clusterManager: ClusterManager;
clusterManager = new ClusterManager();
clusterManager.configuration = {
version: '0.0.1',
pais: [<any>{}]
};
await asyncAssertThrows(
async () => {
await clusterManager.validateConfiguration();
},
'Invalid configuration should not pass validation'
);
clusterManager.allConfigurations[0] = <any>null;
await asyncAssertThrows(async () => {
await clusterManager.validateConfiguration();
}, 'Null configuration should not pass validation');
await asyncAssertThrows(
async () => {
await clusterManager.validateConfiguration();
},
'Null configuration should not pass validation'
);
clusterManager.allConfigurations[0] = {
username: 'openmindstudio',
username: 'openpai',
password: 'Passq1w2e3r4',
rest_server_uri: '10.151.40.234:9186',
webhdfs_uri: '10.151.40.234:50070/webhdfs/v1',
grafana_uri: '10.151.40.234:3000',
k8s_dashboard_uri: '10.151.40.234:9090'
rest_server_uri: 'openpai.vscode.test:9186',
webhdfs_uri: 'openpai.vscode.test:50070/webhdfs/v1',
grafana_uri: 'openpai.vscode.test:3000',
k8s_dashboard_uri: 'openpai.vscode.test:9090'
};
await asyncAssertDoesNotThrow(async () => {
await clusterManager.validateConfiguration();
}, 'Valid configuration should not trigger error');
await asyncAssertDoesNotThrow(
async () => {
await clusterManager.validateConfiguration();
},
'Valid configuration should not trigger error'
);
});
});
});

0 comments on commit c48a6a6

Please sign in to comment.