Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Refactor node side to use inversify #15

Merged
merged 2 commits into from
Mar 31, 2021
Merged
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
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ The DevWorkspace Client is a library for interacting with DevWorkspaces on your

Browser side using kubernetes Rest API:
```typescript
import { DevWorkspaceClient } from '@eclipse-che/devworkspace-client';
import { RestApi } from '@eclipse-che/devworkspace-client';
import axios from 'axios';

const restApiClient = DevWorkspaceClient.getRestApi();
const restApiClient = new RestApi(this.axios)
const workspaceApi = restApiClient.workspaceApi;
const promise = workspaceApi.getAllWorkspaces('my_namespace');
promise.then((workspaces) => {
Expand All @@ -19,11 +19,15 @@ promise.then((workspaces) => {

Node side using @kubernetes/client-node:
```typescript
import { DevWorkspaceClient } from '@eclipse-che/devworkspace-client';
import 'reflect-metadata';
import { container, INVERSIFY_TYPES } from '@eclipse-che/devworkspace-client';

const restApiClient = DevWorkspaceClient.getNodeApi();
const workspaceApi = restApiClient.workspaceApi;
const promise = workspaceApi.getAllWorkspaces('my_namespace');
const devWorkspaceClient = container.get(INVERSIFY_TYPES.IDevWorkspaceClient);
const nodeApi = devWorkspaceClient.getNodeApi({
inCluster: false
});
const workspaceApi = nodeApi.workspaceApi;
const promise = workspaceApi.listInNamespace('my_namespace');
promise.then((workspaces) => {
// process workspaces received from my_namespace
});
Expand Down
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ module.exports = {
moduleDirectories: [
'node_modules',
],
};
setupFiles: ['./src/node/inversify.config.ts']
};
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"license": "EPL-2.0",
"dependencies": {
"@kubernetes/client-node": "^0.14.0",
"axios": "^0.21.1"
"axios": "^0.21.1",
"inversify": "^5.0.5",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
"@types/jest": "^26.0.20",
Expand Down
4 changes: 4 additions & 0 deletions src/browser/che-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export class RestCheApi implements ICheApi {
this.axios = axios;
}

set config(axios: AxiosInstance) {
this.axios = axios;
}

async initializeNamespace(namespace: string): Promise<void> {
const isOpenShift = await isOpenShiftCluster(this.axios);
if (isOpenShift) {
Expand Down
12 changes: 8 additions & 4 deletions src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,28 @@ import {
IDevWorkspaceTemplateApi,
} from '../types';
import { findApi } from './helper';
import { RestDevWorkspaceApi } from './workspace-api';
import { RestDevWorkspaceTemplateApi } from './template-api';
import { RestCheApi } from './che-api';
import { RestDevWorkspaceApi } from './workspace-api';

export class RestApi implements IDevWorkspaceClientApi {
private axios: AxiosInstance;
private _axios: AxiosInstance;
private _workspaceApi: IDevWorkspaceApi;
private _templateApi: IDevWorkspaceTemplateApi;
private _cheApi: ICheApi;
private apiEnabled: boolean | undefined;

constructor(axios: AxiosInstance) {
this.axios = axios;
this._axios = axios;
this._workspaceApi = new RestDevWorkspaceApi(axios);
this._templateApi = new RestDevWorkspaceTemplateApi(axios);
this._cheApi = new RestCheApi(axios);
}

set config(axios: AxiosInstance) {
this._axios = axios;
}

get workspaceApi(): IDevWorkspaceApi {
return this._workspaceApi;
}
Expand All @@ -53,7 +57,7 @@ export class RestApi implements IDevWorkspaceClientApi {
if (this.apiEnabled !== undefined) {
return Promise.resolve(this.apiEnabled);
}
this.apiEnabled = await findApi(this.axios, devWorkspaceApiGroup, devworkspaceVersion);
this.apiEnabled = await findApi(this._axios, devWorkspaceApiGroup, devworkspaceVersion);
return this.apiEnabled;
}
}
16 changes: 10 additions & 6 deletions src/browser/template-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ import { IDevWorkspaceTemplate, IDevWorkspaceTemplateApi } from '../types';
import { devworkspaceVersion, devWorkspaceApiGroup, devworkspaceTemplateSubresource } from '../common';

export class RestDevWorkspaceTemplateApi implements IDevWorkspaceTemplateApi {
private axios: AxiosInstance;
private _axios: AxiosInstance;

constructor(axios: AxiosInstance) {
this.axios = axios;
this._axios = axios;
}

set config(axios: AxiosInstance) {
this._axios = axios;
};

async listInNamespace(namespace: string): Promise<IDevWorkspaceTemplate[]> {
const resp = await this.axios.get(
const resp = await this._axios.get(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspaceTemplateSubresource}`
);
return resp.data.items;
Expand All @@ -32,7 +36,7 @@ export class RestDevWorkspaceTemplateApi implements IDevWorkspaceTemplateApi {
namespace: string,
workspaceName: string
): Promise<IDevWorkspaceTemplate> {
const resp = await this.axios.get(
const resp = await this._axios.get(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspaceTemplateSubresource}/${workspaceName}`
);
return resp.data;
Expand All @@ -41,7 +45,7 @@ export class RestDevWorkspaceTemplateApi implements IDevWorkspaceTemplateApi {
async create(
devworkspaceTemplate: IDevWorkspaceTemplate,
): Promise<IDevWorkspaceTemplate> {
const resp = await this.axios.post(
const resp = await this._axios.post(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${devworkspaceTemplate.metadata.namespace}/${devworkspaceTemplateSubresource}`,
devworkspaceTemplate,
{
Expand All @@ -54,7 +58,7 @@ export class RestDevWorkspaceTemplateApi implements IDevWorkspaceTemplateApi {
}

async delete(namespace: string, name: string): Promise<void> {
this.axios.delete(
this._axios.delete(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspaceTemplateSubresource}/${name}`
);
}
Expand Down
22 changes: 13 additions & 9 deletions src/browser/workspace-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,23 @@ import { AxiosInstance } from 'axios';
import { devfileToDevWorkspace } from '../common/converter';
import { IDevWorkspace, IDevWorkspaceDevfile } from '../types';
import { delay } from '../common/helper';
import { IDevWorkspaceApi } from '../index';
import { IDevWorkspaceApi } from '../types';
import { devworkspaceVersion, devWorkspaceApiGroup, devworkspacePluralSubresource } from '../common';
import { deletePolicy, deletionOptions } from '../common/models';

export class RestDevWorkspaceApi implements IDevWorkspaceApi {
private axios: AxiosInstance;
private _axios: AxiosInstance;

constructor(axios: AxiosInstance) {
this.axios = axios;
this._axios = axios;
}

set config(axios: AxiosInstance) {
this._axios = axios;
};

async listInNamespace(namespace: string): Promise<IDevWorkspace[]> {
const resp = await this.axios.get(
const resp = await this._axios.get(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspacePluralSubresource}`
);
return resp.data.items;
Expand All @@ -36,7 +40,7 @@ export class RestDevWorkspaceApi implements IDevWorkspaceApi {
namespace: string,
workspaceName: string
): Promise<IDevWorkspace> {
const resp = await this.axios.get(
const resp = await this._axios.get(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspacePluralSubresource}/${workspaceName}`
);
return resp.data;
Expand All @@ -50,7 +54,7 @@ export class RestDevWorkspaceApi implements IDevWorkspaceApi {
const devworkspace = devfileToDevWorkspace(devfile, routingClass, started);
const stringifiedDevWorkspace = JSON.stringify(devworkspace);

const resp = await this.axios.post(
const resp = await this._axios.post(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${devfile.metadata.namespace}/${devworkspacePluralSubresource}`,
stringifiedDevWorkspace,
{
Expand Down Expand Up @@ -87,7 +91,7 @@ export class RestDevWorkspaceApi implements IDevWorkspaceApi {
async update(devworkspace: IDevWorkspace): Promise<IDevWorkspace> {
const name = devworkspace.metadata.name;
const namespace = devworkspace.metadata.namespace;
const resp = await this.axios.put(
const resp = await this._axios.put(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspacePluralSubresource}/${name}`,
devworkspace,
{
Expand All @@ -100,7 +104,7 @@ export class RestDevWorkspaceApi implements IDevWorkspaceApi {
}

async delete(namespace: string, name: string): Promise<void> {
await this.axios.delete(
await this._axios.delete(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspacePluralSubresource}/${name}`, {
headers: {
'content-type': 'application/json; charset=utf-8',
Expand All @@ -119,7 +123,7 @@ export class RestDevWorkspaceApi implements IDevWorkspaceApi {
},
];

const resp = await this.axios.patch(
const resp = await this._axios.patch(
`/apis/${devWorkspaceApiGroup}/${devworkspaceVersion}/namespaces/${namespace}/${devworkspacePluralSubresource}/${name}`,
patch,
{
Expand Down
32 changes: 7 additions & 25 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,15 @@
* Red Hat, Inc. - initial API and implementation
*/

import { AxiosInstance } from 'axios';
import { INodeConfig } from './types';
import { RestApi } from './browser';

export * from './common/converter';
export * from './common/index';
export * from './types';
export * from './browser/index';

export class DevWorkspaceClient {

public static getRestApi(axios: AxiosInstance) {
return new RestApi(axios);
}

public static getNodeApi(config: INodeConfig = {
inCluster: true
}) {
if (!DevWorkspaceClient.isItNode()) {
throw new Error('getNodeApi is only available when running in nodejs');
} else {
const nodeApi = require('./node').NodeApi;
return new nodeApi(config);
}
}

private static isItNode() {
return (typeof process !== 'undefined') && (typeof process.versions.node !== 'undefined');
}

// We have to load these with require so that in the browser side module nothing fails when they aren't included in the webpack bundle
const client = require('./node/client').DevWorkspaceClient;
const container = require('./node/inversify.config').container;
export {
client as DevWorkspaceClient,
container
}
8 changes: 5 additions & 3 deletions src/node/che-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ import {
import { projectRequestModel } from '../common/models';
import { handleGenericError } from './errors';
import { findApi } from './helper';
import { injectable } from 'inversify';

@injectable()
export class NodeCheApi implements ICheApi {
private customObjectAPI: k8s.CustomObjectsApi;
private apisApi: k8s.ApisApi;
private customObjectAPI!: k8s.CustomObjectsApi;
private apisApi!: k8s.ApisApi;

constructor(kc: k8s.KubeConfig) {
set config(kc: k8s.KubeConfig) {
this.customObjectAPI = kc.makeApiClient(k8s.CustomObjectsApi);
this.apisApi = kc.makeApiClient(k8s.ApisApi);
}
Expand Down
37 changes: 37 additions & 0 deletions src/node/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2018-2021 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import { IDevWorkspaceClient, IDevWorkspaceClientApi, INodeConfig, INVERSIFY_TYPES } from '../types';
import { inject, injectable } from 'inversify';

@injectable()
export class DevWorkspaceClient implements IDevWorkspaceClient {

constructor(
@inject(INVERSIFY_TYPES.INodeApiFactory) private nodeFactory: (config: INodeConfig) => IDevWorkspaceClientApi) {
}

public getNodeApi(config: INodeConfig = {
inCluster: true
}): IDevWorkspaceClientApi {
if (!this.isItNode()) {
throw new Error('getNodeApi is only available when running in nodejs');
} else {
return this.nodeFactory!(config);
}
}

private isItNode(): boolean {
return (typeof process !== 'undefined') && (typeof process.versions.node !== 'undefined');
}

}
Loading