Skip to content

Commit 4ffa462

Browse files
committed
[WIP] move name validation functions out of OpenShiftItem
Removes one of the cycles and is much cleaner. Signed-off-by: David Thompson <davthomp@redhat.com>
1 parent d1b7182 commit 4ffa462

File tree

6 files changed

+87
-82
lines changed

6 files changed

+87
-82
lines changed

src/openshift/cluster.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { commands, env, ExtensionContext, Progress as VProgress, QuickInputButto
88
import { CliChannel } from '../cli';
99
import { getInstance } from '../odo';
1010
import { Command } from '../odo/command';
11+
import * as NameValidator from '../openshift/nameValidator';
1112
import { CliExitData } from '../util/childProcessUtil';
1213
import { TokenStore } from '../util/credentialManager';
1314
import { Filters } from '../util/filters';
@@ -196,7 +197,7 @@ export class Cluster extends OpenShiftItem {
196197
value: clusterURl,
197198
ignoreFocusOut: true,
198199
prompt: 'Provide new Cluster URL to connect',
199-
validateInput: (value: string) => Cluster.validateUrl('Invalid URL provided', value)
200+
validateInput: (value: string) => NameValidator.validateUrl('Invalid URL provided', value)
200201
}));
201202
} else {
202203
resolve(choice.label);
@@ -413,7 +414,7 @@ export class Cluster extends OpenShiftItem {
413414
ignoreFocusOut: true,
414415
prompt: 'Provide Username for basic authentication to the API server',
415416
value: '',
416-
validateInput: (value: string) => Cluster.emptyName('User name cannot be empty', value)
417+
validateInput: (value: string) => NameValidator.emptyName('User name cannot be empty', value)
417418
})
418419
} else {
419420
username = choice.label;
@@ -463,7 +464,7 @@ export class Cluster extends OpenShiftItem {
463464

464465
static async getUrlFromClipboard(): Promise<string | null> {
465466
const clipboard = await Cluster.readFromClipboard();
466-
if (Cluster.ocLoginCommandMatches(clipboard)) return Cluster.clusterURL(clipboard);
467+
if (NameValidator.ocLoginCommandMatches(clipboard)) return NameValidator.clusterURL(clipboard);
467468
return null;
468469
}
469470

@@ -482,7 +483,7 @@ export class Cluster extends OpenShiftItem {
482483
}
483484

484485
if (!clusterURL && clusterUrlFromClipboard || clusterURL?.trim() === clusterUrlFromClipboard) {
485-
token = Cluster.getToken(await Cluster.readFromClipboard());
486+
token = NameValidator.getToken(await Cluster.readFromClipboard());
486487
clusterURL = clusterUrlFromClipboard;
487488
}
488489

@@ -530,16 +531,16 @@ export class Cluster extends OpenShiftItem {
530531

531532
static async loginUsingClipboardInfo(dashboardUrl: string): Promise<string | null> {
532533
const clipboard = await Cluster.readFromClipboard();
533-
if(!Cluster.ocLoginCommandMatches(clipboard)) {
534+
if(!NameValidator.ocLoginCommandMatches(clipboard)) {
534535
const choice = await window.showErrorMessage('Cannot parse login command in clipboard. Please open cluster dashboard and select `Copy login command` from user name dropdown in the upper right corner. Copy full login command to clipboard. Switch back to VSCode window and press `Login to Sandbox` button again.',
535536
'Open Dashboard');
536537
if (choice === 'Open Dashboard') {
537538
await commands.executeCommand('vscode.open', Uri.parse(dashboardUrl));
538539
}
539540
return;
540541
}
541-
const url = Cluster.clusterURL(clipboard);
542-
const token = Cluster.getToken(clipboard);
542+
const url = NameValidator.clusterURL(clipboard);
543+
const token = NameValidator.getToken(clipboard);
543544
return Cluster.tokenLogin(url, true, token);
544545
}
545546

src/openshift/nameValidator.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
6+
import * as path from 'path';
7+
import validator from 'validator';
8+
9+
export function emptyName(message: string, value: string): string | null {
10+
return validator.isEmpty(value) ? message : null;
11+
}
12+
13+
export function lengthName(message: string, value: string, offset: number): string | null {
14+
return validator.isLength(value, {min: 2, max: 63 - offset}) ? null : message;
15+
}
16+
17+
export function validateUrl(message: string, value: string): string | null {
18+
return validator.isURL(value) ? null : message;
19+
}
20+
21+
export function validateMatches(message: string, value: string): string | null {
22+
return validator.matches(value, '^[a-z]([-a-z0-9]*[a-z0-9])*$') ? null : message;
23+
}
24+
25+
export function validateFilePath(message: string, value: string): string | null {
26+
const proposedPath = path.parse(value);
27+
return /^devfile\.ya?ml$/i.test(proposedPath.base) ? null : message;
28+
}
29+
30+
export function validateRFC1123DNSLabel(message: string, value: string): string | null {
31+
return validator.matches(value, '^[a-z0-9]([-a-z0-9]*[a-z0-9])*$') ? null : message;
32+
}
33+
34+
export function clusterURL(value: string): string | null {
35+
const urlRegex = value.match(/--server=(https?:\/\/[^ ]*)/);
36+
return urlRegex ? urlRegex[1] : null;
37+
}
38+
39+
export function getToken(value: string): string | null {
40+
const tokenRegex = value.match(/--token\s*=\s*(\S*).*/);
41+
return tokenRegex ? tokenRegex[1] : null;
42+
}
43+
44+
export function ocLoginCommandMatches(value: string): string | null {
45+
return clusterURL(value) !== null && getToken(value) !== null ? value : null;
46+
}

src/openshift/openshiftItem.ts

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
*-----------------------------------------------------------------------------------------------*/
55
/* eslint-disable @typescript-eslint/ban-types */
66

7-
import * as path from 'path';
8-
import validator from 'validator';
9-
import { QuickPickItem, commands, window } from 'vscode';
7+
import { commands, QuickPickItem, window } from 'vscode';
108
import { OpenShiftExplorer } from '../explorer';
11-
import { Odo, OpenShiftObject, getInstance } from '../odo';
9+
import { getInstance, Odo, OpenShiftObject } from '../odo';
1210
import { Project } from '../odo/project';
1311
import { ServerlessFunctionView } from '../serverlessFunction/view';
12+
import * as NameValidator from './nameValidator';
1413

1514
export class QuickPickCommand implements QuickPickItem {
1615
constructor (public label: string,
@@ -42,9 +41,9 @@ export default class OpenShiftItem {
4241
prompt: `Provide ${message}`,
4342
ignoreFocusOut: true,
4443
validateInput: async (value: string) => {
45-
let validationMessage = OpenShiftItem.emptyName(`Empty ${message}`, value.trim());
46-
if (!validationMessage) validationMessage = OpenShiftItem.validateMatches(`Not a valid ${message}. Please use lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character`, value);
47-
if (!validationMessage) validationMessage = OpenShiftItem.lengthName(`${message} should be between 2-63 characters`, value, offset ? offset.length : 0);
44+
let validationMessage = NameValidator.emptyName(`Empty ${message}`, value.trim());
45+
if (!validationMessage) validationMessage = NameValidator.validateMatches(`Not a valid ${message}. Please use lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character`, value);
46+
if (!validationMessage) validationMessage = NameValidator.lengthName(`${message} should be between 2-63 characters`, value, offset ? offset.length : 0);
4847
if (!validationMessage) {
4948
try {
5049
const existingResources = await data;
@@ -64,9 +63,9 @@ export default class OpenShiftItem {
6463
prompt: `Provide ${message}`,
6564
ignoreFocusOut: true,
6665
validateInput: async (value: string) => {
67-
let validationMessage = OpenShiftItem.emptyName(`Empty ${message}`, value.trim());
68-
if (!validationMessage) validationMessage = OpenShiftItem.validateRFC1123DNSLabel(`Not a valid ${message}. Please enter name that starts with an alphanumeric character, use lower case alphanumeric characters or '-' and end with an alphanumeric character`, value);
69-
if (!validationMessage) validationMessage = OpenShiftItem.lengthName(`${message} should be between 2-63 characters`, value, offset ? offset.length : 0);
66+
let validationMessage = NameValidator.emptyName(`Empty ${message}`, value.trim());
67+
if (!validationMessage) validationMessage = NameValidator.validateRFC1123DNSLabel(`Not a valid ${message}. Please enter name that starts with an alphanumeric character, use lower case alphanumeric characters or '-' and end with an alphanumeric character`, value);
68+
if (!validationMessage) validationMessage = NameValidator.lengthName(`${message} should be between 2-63 characters`, value, offset ? offset.length : 0);
7069
if (!validationMessage) {
7170
try {
7271
const existingProjects = await data;
@@ -81,45 +80,6 @@ export default class OpenShiftItem {
8180
});
8281
}
8382

84-
static emptyName(message: string, value: string): string | null {
85-
return validator.isEmpty(value) ? message : null;
86-
}
87-
88-
static lengthName(message: string, value: string, offset: number): string | null {
89-
return validator.isLength(value, {min: 2, max: 63 - offset}) ? null : message;
90-
}
91-
92-
static validateUrl(message: string, value: string): string | null {
93-
return validator.isURL(value) ? null : message;
94-
}
95-
96-
static validateMatches(message: string, value: string): string | null {
97-
return validator.matches(value, '^[a-z]([-a-z0-9]*[a-z0-9])*$') ? null : message;
98-
}
99-
100-
static validateFilePath(message: string, value: string): string | null {
101-
const proposedPath = path.parse(value);
102-
return /^devfile\.ya?ml$/i.test(proposedPath.base) ? null : message;
103-
}
104-
105-
static validateRFC1123DNSLabel(message: string, value: string): string | null {
106-
return validator.matches(value, '^[a-z0-9]([-a-z0-9]*[a-z0-9])*$') ? null : message;
107-
}
108-
109-
static clusterURL(value: string): string | null {
110-
const urlRegex = value.match(/--server=(https?:\/\/[^ ]*)/);
111-
return urlRegex ? urlRegex[1] : null;
112-
}
113-
114-
static ocLoginCommandMatches(value: string): string | null {
115-
return OpenShiftItem.clusterURL(value) !== null && OpenShiftItem.getToken(value) !== null ? value : null;
116-
}
117-
118-
static getToken(value: string): string | null {
119-
const tokenRegex = value.match(/--token\s*=\s*(\S*).*/);
120-
return tokenRegex ? tokenRegex[1] : null;
121-
}
122-
12383
}
12484

12585
export function clusterRequired() {

src/webview/common-ext/createComponentHelpers.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
55
import * as fs from 'fs/promises';
6-
import * as path from 'path';
76
import * as JSYAML from 'js-yaml';
7+
import * as path from 'path';
88
import { Registry } from '../../odo/componentType';
9-
import OpenShiftItem from '../../openshift/openshiftItem';
9+
import * as NameValidator from '../../openshift/nameValidator';
1010
import { ComponentTypesView } from '../../registriesView';
1111
import { Devfile, DevfileRegistry } from '../common/devfile';
1212

@@ -90,16 +90,16 @@ export async function isValidProjectFolder(
9090
* @returns the validation message if the component name is invalid, and undefined otherwise
9191
*/
9292
export function validateComponentName(name: string): string {
93-
let validationMessage = OpenShiftItem.emptyName('Please enter a component name.', name);
93+
let validationMessage = NameValidator.emptyName('Please enter a component name.', name);
9494
if (!validationMessage) {
95-
validationMessage = OpenShiftItem.validateMatches(
95+
validationMessage = NameValidator.validateMatches(
9696
`Not a valid component name.
9797
Please use lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character`,
9898
name,
9999
);
100100
}
101101
if (!validationMessage) {
102-
validationMessage = OpenShiftItem.lengthName(
102+
validationMessage = NameValidator.lengthName(
103103
'Component name should be between 2-63 characters',
104104
name,
105105
0,

src/webview/common-ext/utils.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
import * as fs from 'fs/promises';
77
import * as path from 'path';
8-
import { Uri, WebviewPanel, extensions } from 'vscode';
9-
import OpenShiftItem from '../../openshift/openshiftItem';
8+
import { extensions, Uri, WebviewPanel } from 'vscode';
9+
import * as NameValidator from '../../openshift/nameValidator';
1010
import { ExtensionID } from '../../util/constants';
1111
import { gitUrlParse } from '../../util/gitParse';
1212
import { validateGitURLProps } from '../common/propertyTypes';
@@ -98,13 +98,13 @@ export function validateGitURL(event: Message): validateGitURLProps {
9898
}
9999

100100
export function validateName(value: string): string | null {
101-
let validationMessage = OpenShiftItem.emptyName('Required', value.trim());
101+
let validationMessage = NameValidator.emptyName('Required', value.trim());
102102
if (!validationMessage) {
103-
validationMessage = OpenShiftItem.validateMatches(
103+
validationMessage = NameValidator.validateMatches(
104104
'Only lower case alphabets and numeric characters or \'-\', start and ends with only alphabets',
105105
value,
106106
);
107107
}
108-
if (!validationMessage) { validationMessage = OpenShiftItem.lengthName('Should be between 2-63 characters', value, 0); }
108+
if (!validationMessage) { validationMessage = NameValidator.lengthName('Should be between 2-63 characters', value, 0); }
109109
return validationMessage;
110110
}
Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,42 @@
66
import * as chai from 'chai';
77
import * as sinonChai from 'sinon-chai';
88
import { OdoImpl } from '../../../src/odo';
9-
import OpenShiftItem from '../../../src/openshift/openshiftItem';
9+
import * as NameValidator from '../../../src/openshift/nameValidator';
1010
import { wait } from '../../../src/util/async';
1111
import sinon = require('sinon');
1212

13-
const {expect} = chai;
13+
const { expect } = chai;
1414
chai.use(sinonChai);
1515

16-
suite('OpenShiftItem', () => {
17-
16+
suite('nameValidator', function () {
1817
let sandbox: sinon.SinonSandbox;
1918

20-
setup(() => {
19+
setup(function () {
2120
sandbox = sinon.createSandbox();
2221
sandbox.stub(OdoImpl.prototype, 'getActiveCluster').resolves('cluster');
2322
});
2423

25-
teardown(() => {
24+
teardown(function () {
2625
sandbox.restore();
2726
});
2827

29-
test('Wait eventually exits', async () => {
28+
test('Wait eventually exits', async function () {
3029
return wait();
3130
});
3231

33-
suite('validateMatches', ()=> {
34-
35-
test('returns validation message if provided value is not in lower case alphanumeric characters or "-"', ()=> {
36-
const message = 'Not a valid Application name. Please use lower case alphanumeric characters or "-", start with an alphabetic character, and end with an alphanumeric character';
37-
let appNames = OpenShiftItem.validateMatches(message, 'Nodejs-app');
32+
suite('validateMatches', function () {
33+
test('returns validation message if provided value is not in lower case alphanumeric characters or "-"', function () {
34+
const message =
35+
'Not a valid Application name. Please use lower case alphanumeric characters or "-", start with an alphabetic character, and end with an alphanumeric character';
36+
let appNames = NameValidator.validateMatches(message, 'Nodejs-app');
3837
expect(appNames).equals(message);
39-
appNames = OpenShiftItem.validateMatches(message, '2nodejs-app');
38+
appNames = NameValidator.validateMatches(message, '2nodejs-app');
4039
expect(appNames).equals(message);
4140
});
4241

43-
test('returns undefined if provided value is in lower case alphanumeric characters', ()=> {
44-
const validateMatches = OpenShiftItem.validateMatches(undefined, 'nodejs-app');
42+
test('returns undefined if provided value is in lower case alphanumeric characters', function () {
43+
const validateMatches = NameValidator.validateMatches(undefined, 'nodejs-app');
4544
expect(validateMatches).equals(null);
4645
});
4746
});
48-
4947
});

0 commit comments

Comments
 (0)