Skip to content

Commit

Permalink
Replace odo analyze command (#4330)
Browse files Browse the repository at this point in the history
* chaged the image path and removed (formerly Red Hat CodeReady Containers) text

Signed-off-by: msivasubramaniaan <[email protected]>

* removed odo analyze command

Signed-off-by: msivasubramaniaan <[email protected]>

* addressed review comments

Signed-off-by: msivasubramaniaan <[email protected]>

* added alizer test

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed no-unused-vars error

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed no-unused-vars error

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed no-unused-vars error

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed no-unused-vars error

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed no-unused-vars error

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed no-unused-vars error

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed test case fails

Signed-off-by: msivasubramaniaan <[email protected]>

* added deleteComponentConfiguration

Signed-off-by: msivasubramaniaan <[email protected]>

* fixed mapping component description

Signed-off-by: msivasubramaniaan <[email protected]>

* addressed review comments

Signed-off-by: msivasubramaniaan <[email protected]>

* addressed review comments

Signed-off-by: msivasubramaniaan <[email protected]>

---------

Signed-off-by: msivasubramaniaan <[email protected]>
  • Loading branch information
msivasubramaniaan authored Aug 16, 2024
1 parent 4ff8310 commit 44ebc51
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 44 deletions.
35 changes: 35 additions & 0 deletions src/alizer/alizerWrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

import { CommandText } from '../base/command';
import { CliChannel } from '../cli';
import { Uri } from 'vscode';
import { CliExitData } from '../util/childProcessUtil';
import { AlizerAnalyzeResponse } from './types';

/**
* A wrapper around the `alizer` CLI tool.
*
* This class is a stateless singleton.
* This makes it easier to stub its methods than if it were a bunch of directly exported functions.
*/
export class Alizer {
private static INSTANCE = new Alizer();

static get Instance() {
return Alizer.INSTANCE;
}

public async alizerAnalyze(currentFolderPath: Uri): Promise<AlizerAnalyzeResponse> {
const cliData: CliExitData = await CliChannel.getInstance().executeTool(
new CommandText('alizer', `devfile ${currentFolderPath.fsPath}`), undefined, false
);
if (cliData.error || cliData.stderr.length > 0) {
return undefined;
}
const parse = JSON.parse(cliData.stdout) as AlizerAnalyzeResponse[];
return parse[0];
}
}
18 changes: 18 additions & 0 deletions src/alizer/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

export interface Version {
SchemaVersion: number;
Default: boolean;
Version: string;
}

export interface AlizerAnalyzeResponse {
Name: string;
Language: string;
ProjectType: string;
Tags: string[];
Versions: Version[];
}
10 changes: 6 additions & 4 deletions src/downloadUtil/downloadBinaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ export async function downloadFileAndCreateSha256(
console.log(`${current}%`),
);
const currentSHA256 = await hasha.fromFile(currentFile, { algorithm: 'sha256' });
if (currentSHA256 === platform.sha256sum) {
console.log(`Download of ${currentFile} has finished and SHA256 is correct`);
} else {
throw Error(`${currentFile} is downloaded and SHA256 is not correct`);
if (platform.sha256sum) {
if (currentSHA256 === platform.sha256sum) {
console.log(`Download of ${currentFile} has finished and SHA256 is correct`);
} else {
throw Error(`${currentFile} is downloaded and SHA256 is not correct`);
}
}
if (process.env.REMOTE_CONTAINERS === 'true') {
await extractTool(toolsFolder, platform, currentFile);
Expand Down
11 changes: 1 addition & 10 deletions src/odo/odoWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ToolsConfig } from '../tools';
import { ChildProcessUtil, CliExitData } from '../util/childProcessUtil';
import { VsCommandError } from '../vscommand';
import { Command } from './command';
import { AnalyzeResponse, ComponentTypeAdapter, ComponentTypeDescription, DevfileComponentType, Registry } from './componentType';
import { ComponentTypeAdapter, ComponentTypeDescription, DevfileComponentType, Registry } from './componentType';
import { ComponentDescription, StarterProject } from './componentTypeDescription';
import { BindableService } from './odoTypes';

Expand Down Expand Up @@ -194,15 +194,6 @@ export class Odo {
);
}

public async analyze(currentFolderPath: string): Promise<AnalyzeResponse[]> {
const cliData: CliExitData = await this.execute(
new CommandText('odo', 'analyze -o json'),
currentFolderPath,
);
const parse = JSON.parse(cliData.stdout) as AnalyzeResponse[];
return parse;
}

/**
* Returns a list of starter projects for the given Devfile
*
Expand Down
37 changes: 37 additions & 0 deletions src/tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,43 @@
}
}
},
"alizer": {
"description": "Alizer CLI tool",
"vendor": "The Devfile Project",
"name": "alizer",
"version": "1.6.0",
"versionRange": "^1.6.0",
"versionRangeLabel": "version >= 1.6.0",
"dlFileName": "alizer",
"filePrefix": "",
"platform": {
"win32": {
"url": "https://github.com/devfile/alizer/releases/download/v1.6.0/alizer-v1.6.0-windows-amd64.exe",
"dlFileName": "alizer_windows_amd64.exe",
"cmdFileName": "alizer.exe"
},
"darwin": {
"url": "https://github.com/devfile/alizer/releases/download/v1.6.0/alizer-v1.6.0-darwin-amd64",
"dlFileName": "alizer_darwin_amd64",
"cmdFileName": "alizer"
},
"darwin-arm64": {
"url": "https://github.com/devfile/alizer/releases/download/v1.6.0/alizer-v1.6.0-darwin-arm64",
"dlFileName": "alizer_darwin_arm64",
"cmdFileName": "alizer"
},
"linux": {
"url": "https://github.com/devfile/alizer/releases/download/v1.6.0/alizer-v1.6.0-linux-amd64",
"dlFileName": "alizer_linux_amd64",
"cmdFileName": "alizer"
},
"linux-arm64": {
"url": "https://github.com/devfile/alizer/releases/download/v1.6.0/alizer-v1.6.0-linux-arm64",
"dlFileName": "alizer_linux_arm64",
"cmdFileName": "alizer"
}
}
},
"crc": {
"description": "crc openshift container",
"vendor": "Red Hat, Inc.",
Expand Down
3 changes: 2 additions & 1 deletion src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,12 @@ export class ToolsConfig {
public static async selectTool(locations: string[], versionRange: string): Promise<string> {
let result: string;
const funcValue = Platform.OS !== 'win32' ? 'func' : 'func.exe';
const alizerValue = Platform.OS !== 'win32' ? 'alizer' : 'alizer.exe';
// Array.find cannot be used here because of async calls
for (const location of locations) {
// FIXME: see https://github.com/knative/func/issues/2067
// eslint-disable-next-line no-await-in-loop
if (location && (location.endsWith(funcValue) || semver.satisfies(await ToolsConfig.getVersion(location), versionRange))) {
if (location && (location.endsWith(funcValue) || location.endsWith(alizerValue) || semver.satisfies(await ToolsConfig.getVersion(location), versionRange))) {
result = location;
break;
}
Expand Down
37 changes: 23 additions & 14 deletions src/webview/create-component/createComponentLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as tmp from 'tmp';
import { promisify } from 'util';
import * as vscode from 'vscode';
import { extensions, Uri, ViewColumn, WebviewPanel, window } from 'vscode';
import { AnalyzeResponse, ComponentTypeDescription } from '../../odo/componentType';
import { ComponentTypeDescription } from '../../odo/componentType';
import { Endpoint } from '../../odo/componentTypeDescription';
import { Odo } from '../../odo/odoWrapper';
import { ComponentTypesView } from '../../registriesView';
Expand All @@ -30,6 +30,8 @@ import {
} from '../common-ext/createComponentHelpers';
import { loadWebviewHtml, validateGitURL } from '../common-ext/utils';
import { Devfile, DevfileRegistry, TemplateProjectIdentifier } from '../common/devfile';
import { AlizerAnalyzeResponse, Version } from '../../alizer/types';
import { Alizer } from '../../alizer/alizerWrapper';

interface CloneProcess {
status: boolean;
Expand Down Expand Up @@ -518,14 +520,14 @@ export default class CreateComponentLoader {
}

static async getRecommendedDevfile(uri: Uri): Promise<void> {
let analyzeRes: AnalyzeResponse[] = [];
let analyzeRes: AlizerAnalyzeResponse;
let compDescriptions: ComponentTypeDescription[] = [];
try {
void CreateComponentLoader.panel.webview.postMessage({
action: 'getRecommendedDevfileStart'
});
analyzeRes = await Odo.Instance.analyze(uri.fsPath);
compDescriptions = await getCompDescription(analyzeRes);
const alizerAnalyzeRes: AlizerAnalyzeResponse = await Alizer.Instance.alizerAnalyze(uri);
compDescriptions = await getCompDescription(alizerAnalyzeRes);
} catch (error) {
if (error.message.toLowerCase().indexOf('failed to parse the devfile') !== -1) {
const actions: Array<string> = ['Yes', 'Cancel'];
Expand All @@ -539,7 +541,7 @@ export default class CreateComponentLoader {
const file = await fs.readFile(devFileV1Path, 'utf8');
const devfileV1 = JSYAML.load(file.toString()) as DevfileV1;
await fs.unlink(devFileV1Path);
analyzeRes = await Odo.Instance.analyze(uri.fsPath);
analyzeRes = await Alizer.Instance.alizerAnalyze(uri);
compDescriptions = await getCompDescription(analyzeRes);
const endPoints = getEndPoints(compDescriptions[0]);
const devfileV2 = DevfileConverter.getInstance().devfileV1toDevfileV2(
Expand Down Expand Up @@ -587,18 +589,25 @@ export default class CreateComponentLoader {
}
}

async function getCompDescription(devfiles: AnalyzeResponse[]): Promise<ComponentTypeDescription[]> {
async function getCompDescription(devfile: AlizerAnalyzeResponse): Promise<ComponentTypeDescription[]> {
const compDescriptions = await ComponentTypesView.instance.getCompDescriptions();
if (devfiles.length === 0) {
if (!devfile) {
return Array.from(compDescriptions);
}
return Array.from(compDescriptions).filter(({ name, version, registry }) =>
devfiles.some(
(res) =>
res.devfile === name &&
res.devfileVersion === version &&
res.devfileRegistry === registry.name,
),
return Array.from(compDescriptions).filter((compDesc) => {
if (devfile.Name === compDesc.name && getVersion(devfile.Versions, compDesc.version)) {
return compDesc;
}
}
);
}

function getVersion(devfileVersions: Version[], matchedVersion: string): Version {
return devfileVersions.find((devfileVersion) => {
if (devfileVersion.Version === matchedVersion) {
return devfileVersion;
}
}
);
}

Expand Down
134 changes: 134 additions & 0 deletions test/integration/alizerWrapper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/
import { fail } from 'assert';
import { expect } from 'chai';
import * as fs from 'fs/promises';
import { suite, suiteSetup } from 'mocha';
import * as tmp from 'tmp';
import * as path from 'path';
import { promisify } from 'util';
import { Uri, workspace } from 'vscode';
import { Oc } from '../../src/oc/ocWrapper';
import { Odo } from '../../src/odo/odoWrapper';
import { LoginUtil } from '../../src/util/loginUtil';
import { Alizer } from '../../src/alizer/alizerWrapper';

suite('./alizer/alizerWrapper.ts', function () {
const isOpenShift: boolean = Boolean(parseInt(process.env.IS_OPENSHIFT, 10)) || false;
const clusterUrl = process.env.CLUSTER_URL || 'https://api.crc.testing:6443';
const username = process.env.CLUSTER_USER || 'developer';
const password = process.env.CLUSTER_PASSWORD || 'developer';

suiteSetup(async function () {
if (isOpenShift) {
try {
await LoginUtil.Instance.logout();
} catch {
// do nothing
}
await Oc.Instance.loginWithUsernamePassword(clusterUrl, username, password);
}
});

suiteTeardown(async function () {
// ensure projects are cleaned up
try {
await Oc.Instance.deleteProject('my-test-project-1');
} catch {
// do nothing
}
try {
await Oc.Instance.deleteProject('my-test-project-2');
} catch {
// do nothing
}

if (isOpenShift) {
await LoginUtil.Instance.logout();
}
});

suite('analyse folder', function () {
const project1 = 'my-test-project-1';

let tmpFolder1: Uri;
let tmpFolder2: Uri;

suiteSetup(async function () {
await Oc.Instance.createProject(project1);
tmpFolder1 = Uri.parse(await promisify(tmp.dir)());
tmpFolder2 = Uri.parse(await promisify(tmp.dir)());
await Odo.Instance.createComponentFromFolder(
'nodejs',
undefined,
'component1',
tmpFolder1,
'nodejs-starter',
);
await Odo.Instance.createComponentFromFolder(
'go',
undefined,
'component2',
tmpFolder2,
'go-starter',
);
});

suiteTeardown(async function () {
if (isOpenShift) {
await Oc.Instance.loginWithUsernamePassword(clusterUrl, username, password);
}
const newWorkspaceFolders = workspace.workspaceFolders.filter((workspaceFolder) => {
const fsPath = workspaceFolder.uri.fsPath;
return (fsPath !== tmpFolder1.fsPath && fsPath !== tmpFolder2.fsPath);
});
workspace.updateWorkspaceFolders(0, workspace.workspaceFolders.length, ...newWorkspaceFolders);
await fs.rm(tmpFolder1.fsPath, { force: true, recursive: true });
await fs.rm(tmpFolder2.fsPath, { force: true, recursive: true });
await Oc.Instance.deleteProject(project1);
});

test('analyze()', async function () {
const analysis1 = await Alizer.Instance.alizerAnalyze(tmpFolder1);
expect(analysis1).to.exist;
expect(analysis1.Name).to.equal('nodejs');
const analysis2 = await Alizer.Instance.alizerAnalyze(tmpFolder2);
expect(analysis2).to.exist;
expect(analysis2.Name).to.equal('go');
});
});

suite('create component', function() {

const COMPONENT_TYPE = 'dotnet50';

let tmpFolder: string;

suiteSetup(async function() {
tmpFolder = await promisify(tmp.dir)();
});

suiteTeardown(async function() {
await fs.rm(tmpFolder, { recursive: true, force: true });
});

test('createComponentFromTemplateProject()', async function() {
await Odo.Instance.createComponentFromTemplateProject(tmpFolder, 'my-component', 8080, COMPONENT_TYPE, 'DefaultDevfileRegistry', 'dotnet50-example');
try {
await fs.access(path.join(tmpFolder, 'devfile.yaml'));
} catch {
fail('Expected devfile to be created');
}
});

test('analyze()', async function() {
const analysis = await Alizer.Instance.alizerAnalyze(Uri.file(tmpFolder));
expect(analysis.Name).to.equal(COMPONENT_TYPE);
});

});

test('deleteComponentConfiguration');
});
15 changes: 0 additions & 15 deletions test/integration/odoWrapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,6 @@ suite('./odo/odoWrapper.ts', function () {
expect(componentDescription2).to.exist;
expect(componentDescription2.managedBy).to.equal('odo');
});

test('analyze()', async function () {
const analysis1 = await Odo.Instance.analyze(tmpFolder1.fsPath);
expect(analysis1).to.exist;
expect(analysis1[0].devfile).to.equal('nodejs');
const analysis2 = await Odo.Instance.analyze(tmpFolder2.fsPath);
expect(analysis2).to.exist;
expect(analysis2[0].devfile).to.equal('go');
});
});

suite('registries', function () {
Expand Down Expand Up @@ -207,12 +198,6 @@ suite('./odo/odoWrapper.ts', function () {
}
});

test('analyze()', async function() {
const [analysis] = await Odo.Instance.analyze(tmpFolder);
expect(analysis.name).to.equal(path.basename(tmpFolder).toLocaleLowerCase());
expect(analysis.devfile).to.equal(COMPONENT_TYPE);
});

test('deleteComponentConfiguration()', async function() {
await Odo.Instance.deleteComponentConfiguration(tmpFolder);
try {
Expand Down

0 comments on commit 44ebc51

Please sign in to comment.