Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace odo analyze command #4330

Merged
Merged
Show file tree
Hide file tree
Changes from 4 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
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];
}
}
19 changes: 19 additions & 0 deletions src/alizer/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/


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
27 changes: 13 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 } from '../../alizer/types';
import { Alizer } from '../../alizer/alizerWrapper';

interface CloneProcess {
status: boolean;
Expand Down Expand Up @@ -514,14 +516,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 @@ -535,7 +537,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 @@ -583,18 +585,15 @@ 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(({ name, version }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (foo) {
  return true;
}
return false;

is the same as

return foo;

If you find the first version easier to understand feel free to keep it, but I personally tend to prefer the second version.

devfile.Name === name;
devfile.Versions[0].Version === version
}
);
}

Expand Down
14 changes: 7 additions & 7 deletions test/integration/odoWrapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ 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('./odo/odoWrapper.ts', function () {
const isOpenShift: boolean = Boolean(parseInt(process.env.IS_OPENSHIFT, 10)) || false;
Expand Down Expand Up @@ -100,12 +101,12 @@ suite('./odo/odoWrapper.ts', function () {
});

test('analyze()', async function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@msivasubramaniaan The test('analyze()', async function () { test case should probably also be moved out from test/integration/odoWrapper.test.ts into a separate test, shouldn't it?

const analysis1 = await Odo.Instance.analyze(tmpFolder1.fsPath);
const analysis1 = await Alizer.Instance.alizerAnalyze(tmpFolder1);
expect(analysis1).to.exist;
expect(analysis1[0].devfile).to.equal('nodejs');
const analysis2 = await Odo.Instance.analyze(tmpFolder2.fsPath);
expect(analysis1[0].Name).to.equal('nodejs');
const analysis2 = await Alizer.Instance.alizerAnalyze(tmpFolder2);
expect(analysis2).to.exist;
expect(analysis2[0].devfile).to.equal('go');
expect(analysis2[0].Name).to.equal('go');
});
});

Expand Down Expand Up @@ -208,9 +209,8 @@ 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);
const analysis = await Alizer.Instance.alizerAnalyze(Uri.file(tmpFolder));
expect(analysis.Name).to.equal(COMPONENT_TYPE);
});

test('deleteComponentConfiguration()', async function() {
Expand Down
Loading