Skip to content

Commit bb30328

Browse files
committed
[WIP] refactor ServerlessFunction -> ServerlessFunctionModel
Signed-off-by: David Thompson <davthomp@redhat.com>
1 parent 4ffa462 commit bb30328

File tree

4 files changed

+106
-116
lines changed

4 files changed

+106
-116
lines changed

src/extension.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { extendClusterExplorer } from './k8s/clusterExplorer';
2121
import { Cluster } from './openshift/cluster';
2222
import { Component } from './openshift/component';
2323
import { ComponentTypesView } from './registriesView';
24-
import { ServerlessFunctionImpl } from './serverlessFunction/functionImpl';
2524
import { ServerlessFunctionView } from './serverlessFunction/view';
2625
import { startTelemetry } from './telemetry';
2726
import { ToolsConfig } from './tools';
@@ -95,7 +94,6 @@ export async function activate(extensionContext: ExtensionContext): Promise<unkn
9594
...Component.init(),
9695
ComponentTypesView.instance.createTreeView('openshiftComponentTypesView'),
9796
ServerlessFunctionView.getInstance(),
98-
ServerlessFunctionImpl.Instance,
9997
ComponentsTreeDataProvider.instance.createTreeView('openshiftComponentsView'),
10098
setupWorkspaceDevfileContext(),
10199
];
Lines changed: 48 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -3,125 +3,39 @@
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
55

6-
import * as cp from 'child_process';
76
import * as fs from 'fs-extra';
8-
import { dump } from 'js-yaml';
97
import * as path from 'path';
10-
import { Disposable, Uri, window, workspace } from 'vscode';
8+
import { Disposable, Uri, workspace } from 'vscode';
119
import { CommandText } from '../base/command';
1210
import { CliChannel } from '../cli';
1311
import { DeploymentConfig } from '../k8s/deploymentConfig';
14-
import { OdoImpl } from '../odo';
15-
import { CliExitData } from '../util/childProcessUtil';
16-
import { VsCommandError } from '../vscommand';
17-
import { ServerlessCommand, Utils } from './commands';
12+
import { Utils } from './commands';
1813
import { Functions } from './functions';
1914
import { DeployedFunction, FunctionContent, FunctionObject, FunctionStatus } from './types';
20-
import { ServerlessFunctionView } from './view';
2115

22-
export interface ServerlessFunction extends Disposable {
23-
getLocalFunctions(): Promise<FunctionObject[]>;
24-
createFunction(language: string, template: string, location: string, image: string): Promise<CliExitData>;
16+
export interface View {
17+
refresh(): void;
2518
}
2619

27-
export class ServerlessFunctionImpl implements ServerlessFunction {
28-
private static instance: ServerlessFunction = new ServerlessFunctionImpl();
20+
export class ServerlessFunctionModel implements Disposable {
2921

3022
private watchers: fs.FSWatcher[] = [];
3123
private workspaceWatcher: Disposable;
24+
private view: View;
3225

33-
public static get Instance(): ServerlessFunction {
34-
return ServerlessFunctionImpl.instance;
35-
}
36-
37-
private constructor() {
26+
public constructor(view: View) {
27+
this.view = view;
3828
this.addWatchers();
3929
this.workspaceWatcher = workspace.onDidChangeWorkspaceFolders((_e) => {
4030
for (const watcher of this.watchers) {
4131
watcher.close();
4232
}
43-
ServerlessFunctionView.getInstance().refresh();
33+
this.view.refresh();
4434
this.addWatchers();
4535
});
4636
}
4737

48-
private addWatchers() {
49-
if (workspace.workspaceFolders) {
50-
for (const workspaceFolder of workspace.workspaceFolders) {
51-
this.watchers.push(
52-
fs.watch(workspaceFolder.uri.fsPath, (_event, filename) => {
53-
if (filename === 'func.yaml') {
54-
ServerlessFunctionView.getInstance().refresh();
55-
}
56-
}),
57-
);
58-
}
59-
}
60-
}
61-
62-
private async getListItems(command: CommandText, fail = false) {
63-
const listCliExitData = await CliChannel.getInstance().executeTool(
64-
command,
65-
undefined,
66-
fail,
67-
);
68-
try {
69-
return JSON.parse(listCliExitData.stdout) as FunctionObject[];
70-
} catch (err) {
71-
return [];
72-
}
73-
}
74-
75-
private async getDeployedFunctions(): Promise<FunctionObject[]> {
76-
return this.getListItems(DeploymentConfig.command.getDeploymentFunctions());
77-
}
78-
79-
async createFunction(
80-
language: string,
81-
template: string,
82-
location: string,
83-
image: string,
84-
): Promise<CliExitData> {
85-
let functionResponse: CliExitData;
86-
try {
87-
const response = await OdoImpl.Instance.execute(
88-
ServerlessCommand.createFunction(language, template, location),
89-
);
90-
if (response && !response.error) {
91-
const yamlContent = await Utils.getFuncYamlContent(location);
92-
if (yamlContent) {
93-
yamlContent.image = image;
94-
await fs.rm(path.join(location, 'func.yaml'));
95-
await fs.writeFile(
96-
path.join(location, 'func.yaml'),
97-
dump(yamlContent),
98-
'utf-8',
99-
);
100-
functionResponse = {
101-
error: undefined,
102-
stderr: '',
103-
stdout: 'Success',
104-
};
105-
}
106-
} else {
107-
await fs.rmdir(location);
108-
functionResponse = response;
109-
}
110-
} catch (err) {
111-
if (err instanceof VsCommandError) {
112-
void window.showErrorMessage(err.message);
113-
}
114-
await fs.rmdir(location);
115-
functionResponse = {
116-
error: err as cp.ExecException,
117-
stderr: '',
118-
stdout: '',
119-
};
120-
}
121-
return functionResponse;
122-
}
123-
124-
async getLocalFunctions(): Promise<FunctionObject[]> {
38+
public async getLocalFunctions(): Promise<FunctionObject[]> {
12539
const functionList: FunctionObject[] = [];
12640
const folders: Uri[] = [];
12741
if (workspace.workspaceFolders) {
@@ -172,7 +86,14 @@ export class ServerlessFunctionImpl implements ServerlessFunction {
17286
return functionList;
17387
}
17488

175-
getDeployFunction(
89+
public dispose() {
90+
for (const watcher of this.watchers) {
91+
watcher.close();
92+
}
93+
this.workspaceWatcher.dispose();
94+
}
95+
96+
private getDeployFunction(
17697
funcData: FunctionContent,
17798
deployedFunctions: FunctionObject[],
17899
): DeployedFunction {
@@ -192,19 +113,39 @@ export class ServerlessFunctionImpl implements ServerlessFunction {
192113
return { status: FunctionStatus.LOCALONLY, url: '' } as DeployedFunction;
193114
}
194115

195-
dispose() {
196-
for (const watcher of this.watchers) {
197-
watcher.close();
116+
private async checkImage(folderUri: Uri): Promise<boolean> {
117+
const yamlContent = await Utils.getFuncYamlContent(folderUri.fsPath);
118+
return Functions.imageRegex.test(yamlContent?.image);
119+
}
120+
121+
private addWatchers() {
122+
if (workspace.workspaceFolders) {
123+
for (const workspaceFolder of workspace.workspaceFolders) {
124+
this.watchers.push(
125+
fs.watch(workspaceFolder.uri.fsPath, (_event, filename) => {
126+
if (filename === 'func.yaml') {
127+
this.view.refresh();
128+
}
129+
}),
130+
);
131+
}
198132
}
199-
this.workspaceWatcher.dispose();
200133
}
201134

202-
async checkImage(folderUri: Uri): Promise<boolean> {
203-
const yamlContent = await Utils.getFuncYamlContent(folderUri.fsPath);
204-
return Functions.imageRegex.test(yamlContent?.image);
135+
private async getListItems(command: CommandText, fail = false) {
136+
const listCliExitData = await CliChannel.getInstance().executeTool(
137+
command,
138+
undefined,
139+
fail,
140+
);
141+
try {
142+
return JSON.parse(listCliExitData.stdout) as FunctionObject[];
143+
} catch (err) {
144+
return [];
145+
}
205146
}
206-
}
207147

208-
export function serverlessInstance(): ServerlessFunction {
209-
return ServerlessFunctionImpl.Instance;
148+
private async getDeployedFunctions(): Promise<FunctionObject[]> {
149+
return this.getListItems(DeploymentConfig.command.getDeploymentFunctions());
150+
}
210151
}

src/serverlessFunction/view.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { FileContentChangeNotifier, WatchUtil } from '../util/watch';
2727
import { vsCommand } from '../vscommand';
2828
import ServerlessFunctionViewLoader from '../webview/serverless-function/serverlessFunctionLoader';
2929
import ManageRepositoryViewLoader from '../webview/serverless-manage-repository/manageRepositoryLoader';
30-
import { ServerlessFunction, serverlessInstance } from './functionImpl';
30+
import { ServerlessFunctionModel } from './functionModel';
3131
import { Functions } from './functions';
3232
import { FunctionContextType, FunctionObject, FunctionStatus } from './types';
3333

@@ -51,9 +51,10 @@ export class ServerlessFunctionView implements TreeDataProvider<ExplorerItem>, D
5151
readonly onDidChangeTreeData: Event<ExplorerItem | undefined> = this
5252
.eventEmitter.event;
5353

54-
private serverlessFunction: ServerlessFunction = serverlessInstance();
54+
private serverlessFunction: ServerlessFunctionModel;
5555

5656
private constructor() {
57+
this.serverlessFunction = new ServerlessFunctionModel(this);
5758
try {
5859
this.kubeConfig = new KubeConfigUtils();
5960
this.kubeContext = this.kubeConfig.getContextObject(this.kubeConfig.currentContext);
@@ -197,6 +198,7 @@ export class ServerlessFunctionView implements TreeDataProvider<ExplorerItem>, D
197198
dispose(): void {
198199
this.fsw?.watcher?.close();
199200
this.treeView.dispose();
201+
this.serverlessFunction.dispose();
200202
}
201203

202204
@vsCommand('openshift.Serverless.createFunction')

src/webview/serverless-function/serverlessFunctionLoader.ts

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,29 @@
22
* Copyright (c) Red Hat, Inc. All rights reserved.
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
5+
import * as cp from 'child_process';
56
import * as crypto from 'crypto';
7+
import * as fs from 'fs/promises';
8+
import * as JSYAML from 'js-yaml';
69
import * as path from 'path';
710
import * as vscode from 'vscode';
8-
import { serverlessInstance } from '../../serverlessFunction/functionImpl';
11+
import { OdoImpl } from '../../odo';
12+
import { ServerlessCommand, Utils } from '../../serverlessFunction/commands';
913
import { Functions } from '../../serverlessFunction/functions';
1014
import { InvokeFunction } from '../../serverlessFunction/types';
1115
import { CliExitData } from '../../util/childProcessUtil';
1216
import { ExtensionID } from '../../util/constants';
1317
import { Progress } from '../../util/progress';
1418
import { selectWorkspaceFolder, selectWorkspaceFolders } from '../../util/workspace';
19+
import { VsCommandError } from '../../vscommand';
1520
import { loadWebviewHtml, validateName } from '../common-ext/utils';
1621

1722
export interface ServiceBindingFormResponse {
1823
selectedService: string;
1924
bindingName: string;
2025
}
2126

22-
async function gitImportMessageListener(panel: vscode.WebviewPanel, event: any): Promise<any> {
27+
async function messageListener(panel: vscode.WebviewPanel, event: any): Promise<any> {
2328
let response: CliExitData;
2429
const eventName = event.action;
2530
const functionName = event.name;
@@ -63,7 +68,7 @@ async function gitImportMessageListener(panel: vscode.WebviewPanel, event: any):
6368
await Progress.execFunctionWithProgress(
6469
`Creating function '${functionName}'`,
6570
async () => {
66-
response = await serverlessInstance().createFunction(event.language, event.template, selctedFolder.fsPath, event.selectedImage);
71+
response = await ServerlessFunctionViewLoader.createFunction(event.language, event.template, selctedFolder.fsPath, event.selectedImage);
6772
});
6873
if (response && response.error) {
6974
void vscode.window.showErrorMessage(`Error while creating the function ${functionName}`);
@@ -174,7 +179,7 @@ export default class ServerlessFunctionViewLoader {
174179
'serverlessFunctionViewer',
175180
panel,
176181
);
177-
panel.webview.onDidReceiveMessage((e) => gitImportMessageListener(panel, e));
182+
panel.webview.onDidReceiveMessage((e) => messageListener(panel, e));
178183

179184
panel.onDidDispose(() => {
180185
if (ServerlessFunctionViewLoader.invokePanelMap.has(title)) {
@@ -185,5 +190,49 @@ export default class ServerlessFunctionViewLoader {
185190

186191
return Promise.resolve(panel);
187192
}
188-
}
189193

194+
static async createFunction(
195+
language: string,
196+
template: string,
197+
location: string,
198+
image: string,
199+
): Promise<CliExitData> {
200+
let functionResponse: CliExitData;
201+
try {
202+
const response = await OdoImpl.Instance.execute(
203+
ServerlessCommand.createFunction(language, template, location),
204+
);
205+
if (response && !response.error) {
206+
const yamlContent = await Utils.getFuncYamlContent(location);
207+
if (yamlContent) {
208+
yamlContent.image = image;
209+
await fs.rm(path.join(location, 'func.yaml'));
210+
await fs.writeFile(
211+
path.join(location, 'func.yaml'),
212+
JSYAML.dump(yamlContent),
213+
'utf-8',
214+
);
215+
functionResponse = {
216+
error: undefined,
217+
stderr: '',
218+
stdout: 'Success',
219+
};
220+
}
221+
} else {
222+
await fs.rmdir(location);
223+
functionResponse = response;
224+
}
225+
} catch (err) {
226+
if (err instanceof VsCommandError) {
227+
void vscode.window.showErrorMessage(err.message);
228+
}
229+
await fs.rmdir(location);
230+
functionResponse = {
231+
error: err as cp.ExecException,
232+
stderr: '',
233+
stdout: '',
234+
};
235+
}
236+
return functionResponse;
237+
}
238+
}

0 commit comments

Comments
 (0)