Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ src/webview/welcome
src/webview/helm-chart
src/webview/feedback
src/webview/serverless-function
src/webview/serverless-manage-repository
# vendored from https://github.com/IonicaBizau/git-url-parse, see https://github.com/IonicaBizau/git-url-parse/pull/159
src/util/gitParse.ts
test/sandbox-registration
1 change: 1 addition & 0 deletions build/esbuild.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const webviews = [
'welcome',
'feedback',
'serverless-function',
'serverless-manage-repository',
'add-service-binding',
];

Expand Down
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,12 @@
"category": "OpenShift",
"icon": "$(plus)"
},
{
"command": "openshift.Serverless.manageRepository",
"title": "Manage Knative Function Template Repositories",
"category": "OpenShift",
"icon": "$(gist)"
},
{
"command": "openshift.Serverless.refresh",
"title": "Refresh Serverless Function View",
Expand Down Expand Up @@ -1299,6 +1305,11 @@
"when": "view == openshiftServerlessFunctionsView",
"group": "navigation@1"
},
{
"command": "openshift.Serverless.manageRepository",
"when": "view == openshiftServerlessFunctionsView",
"group": "navigation@2"
},
{
"command": "openshift.component.openCreateComponent",
"when": "view == openshiftComponentsView",
Expand Down
40 changes: 31 additions & 9 deletions src/serverlessFunction/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,41 @@ export class ServerlessCommand {
}

static config(functionPath: string, mode: string, isAdd: boolean): CommandText {
const option = isAdd ? mode === 'git' ? 'set' : 'add' : 'remove';
const commandText = new CommandText('func', 'config', [
new CommandOption(mode),
new CommandOption(option),
new CommandOption('-p', functionPath)
]);
if (isAdd) {
if (mode === 'git') {
commandText.addOption(new CommandOption('set'));
} else {
commandText.addOption(new CommandOption('add'));
}
} else {
commandText.addOption(new CommandOption('remove'));
}
return commandText;
}

static addRepo(name: string, gitURL: string): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('add'));
commandText.addOption(new CommandOption(name));
commandText.addOption(new CommandOption(gitURL));
return commandText;
}

static deleteRepo(name: string): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('remove'));
commandText.addOption(new CommandOption(name));
return commandText;
}

static list(): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('list'));
return commandText;
}

static renameRepo(oldName: string, newName: string): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('rename'));
commandText.addOption(new CommandOption(oldName));
commandText.addOption(new CommandOption(newName));
return commandText;
}
}
101 changes: 101 additions & 0 deletions src/serverlessFunction/manageRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { OdoImpl } from '../odo';
import sendTelemetry from '../telemetry';
import { Progress } from '../util/progress';
import { ServerlessCommand } from './commands';

export class ManageRepository {

private static instance: ManageRepository;

static getInstance(): ManageRepository {
if (!ManageRepository.instance) {
ManageRepository.instance = new ManageRepository();
}
return ManageRepository.instance;
}

public async deleteRepo(name: string): Promise<boolean> {
await sendTelemetry('openshift.managerepo.delete', {
name
});
const result = await OdoImpl.Instance.execute(ServerlessCommand.deleteRepo(name), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.delete.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
return false;
}
return true;
}

public async renameRepo(oldName: string, newName: string): Promise<boolean> {
await sendTelemetry('openshift.managerepo.rename', {
oldName,
newName
});
const result = await OdoImpl.Instance.execute(ServerlessCommand.renameRepo(oldName, newName), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.rename.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
return false;
}
await sendTelemetry('openshift.managerepo.rename.success', {
message: `Repo ${newName} renamed successfully`
});
return true;
}

public async addRepo(name: string, url: string): Promise<boolean> {
await sendTelemetry('openshift.managerepo.add', {
name, url
});
return new Promise<boolean>((resolve, _reject) => {
void Progress.execFunctionWithProgress(`Adding repository ${name}`, async () => {
Comment thread
msivasubramaniaan marked this conversation as resolved.
Outdated
const result = await OdoImpl.Instance.execute(ServerlessCommand.addRepo(name, url), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.add.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
resolve(false);
} else if (result.stdout.length === 0 && result.stderr.length === 0) {
await sendTelemetry('openshift.managerepo.add.success', {
name,
message: 'Repo added successfully'
});
void vscode.window.showInformationMessage(`Repository ${name} added successfully`);
resolve(true);
}
await sendTelemetry('openshift.managerepo.add.error', {
error: result.stderr
});
resolve(false);
});
});
}

public async list(): Promise<string[]> {
await sendTelemetry('openshift.managerepo.list');
const result = await OdoImpl.Instance.execute(ServerlessCommand.list(), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.list.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
return [];
}
await sendTelemetry('openshift.managerepo.list.success', {
repos: result.stdout.split('\n')
});
return result.stdout.split('\n');
}
}
6 changes: 6 additions & 0 deletions src/serverlessFunction/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { FunctionContextType, FunctionObject, FunctionStatus } from './types';
import ServerlessFunctionViewLoader from '../webview/serverless-function/serverlessFunctionLoader';
import { Functions } from './functions';
import { vsCommand } from '../vscommand';
import ManageRepositoryViewLoader from '../webview/serverless-manage-repository/manageRepositoryLoader';

const kubeConfigFolder: string = path.join(Platform.getUserHomePath(), '.kube');

Expand Down Expand Up @@ -203,6 +204,11 @@ export class ServerlessFunctionView implements TreeDataProvider<ExplorerItem>, D
await ServerlessFunctionViewLoader.loadView('Serverless Function - Create');
}

@vsCommand('openshift.Serverless.manageRepository')
static async openManageRepository(): Promise<void> {
await ManageRepositoryViewLoader.loadView('Manage Repository');
}

@vsCommand('openshift.Serverless.refresh')
static refresh(target?: ExplorerItem) {
ServerlessFunctionView.getInstance().refresh(target);
Expand Down
69 changes: 68 additions & 1 deletion src/webview/common-ext/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import { Uri, WebviewPanel, extensions } from 'vscode';
import OpenShiftItem from '../../openshift/openshiftItem';
import { ExtensionID } from '../../util/constants';
import { gitUrlParse } from '../../util/gitParse';
import { validateGitURLProps } from '../common/propertyTypes';

export type Message = {
action: string;
data: any;
};

export async function loadWebviewHtml(webviewName: string, webviewPanel: WebviewPanel, additionalInjections?: Map<string, string>): Promise<string> {

Expand All @@ -28,7 +36,7 @@ export async function loadWebviewHtml(webviewName: string, webviewPanel: Webview
style-src 'self' vscode-resource: 'unsafe-inline';">`;
const htmlWithDefaultInjections = `${htmlString}`
.replace('%PLATFORM%', process.platform)
.replace('%SCRIPT%',`${reactJavascriptUri}`)
.replace('%SCRIPT%', `${reactJavascriptUri}`)
.replace('%BASE_URL%', `${reactJavascriptUri}`)
.replace('%STYLE%', `${reactStylesheetUri}`)
.replace('<!-- meta http-equiv="Content-Security-Policy" -->', meta);
Expand All @@ -41,3 +49,62 @@ export async function loadWebviewHtml(webviewName: string, webviewPanel: Webview
}
return htmlWithAdditionalInjections;
}

function isGitURL(host: string): boolean {
return [
'github.com',
'bitbucket.org',
'gitlab.com',
'git.sr.ht',
'codeberg.org',
'gitea.com',
].includes(host);
}

export function validateGitURL(event: Message): validateGitURLProps {
if (typeof event.data === 'string' && (event.data).trim().length === 0) {
return {
url: event.data,
error: true,
helpText: 'Please enter a Git URL.'
} as validateGitURLProps
}
try {
const parse = gitUrlParse(event.data);
const isGitRepo = isGitURL(parse.host);
if (!isGitRepo) {
throw 'Invalid Git URL';
}
if (parse.organization !== '' && parse.name !== '') {
return {
url: event.data,
error: false,
helpText: 'The git repo URL is valid.'
} as validateGitURLProps
}
return {
url: event.data,
error: true,
helpText: 'URL is missing organization or repo name.'
} as validateGitURLProps

} catch (e) {
return {
url: event.data,
error: true,
helpText: 'Invalid Git URL.'
} as validateGitURLProps
}
}

export function validateName(value: string): string | null {
let validationMessage = OpenShiftItem.emptyName('Required', value.trim());
if (!validationMessage) {
validationMessage = OpenShiftItem.validateMatches(
'Only lower case alphabets and numeric characters or \'-\', start and ends with only alphabets',
value,
);
}
if (!validationMessage) { validationMessage = OpenShiftItem.lengthName('Should be between 2-63 characters', value, 0); }
return validationMessage;
}
8 changes: 6 additions & 2 deletions src/webview/common/propertyTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

import { ChangeEvent } from 'react';
import { ComponentTypeDescription, Registry } from '../../odo/componentType';
import { StarterProject } from '../../odo/componentTypeDescription';
import { ChartResponse } from '../helm-chart/helmChartType';
Expand Down Expand Up @@ -84,3 +82,9 @@ export interface RunFunctionPageProps extends DefaultProps {
skip: (stepCount: number) => void;
onRunSubmit: (folderPath: Uri, build: boolean) => void;
}

export interface validateGitURLProps {
url: string;
error: boolean;
helpText: string;
}
18 changes: 0 additions & 18 deletions src/webview/common/utils.ts

This file was deleted.

Loading