Skip to content

Commit 129017d

Browse files
committed
Add 'New Component' command to Component Types view
This fix adds 'New Component' command fo ImageStreamTag, DevfileComponentType and StarterProject tree items in Component Types View. Depending on context 'New Component' command is skipping certain steps of regular workflow, because some of information like component type kind, name, version and starter project can be extracted from context. It also keep in place existing checks. For example `New Component` command executed on StarterProject will not use starter project in case not empty context folder selected and etc. Signed-off-by: Denis Golovin dgolovin@redhat.com
1 parent 96e6ba6 commit 129017d

File tree

5 files changed

+88
-31
lines changed

5 files changed

+88
-31
lines changed

package.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,11 @@
761761
"command": "openshift.componentType.cloneStarterProjectRepository",
762762
"title": "Clone Sample Project repository to workspace",
763763
"category": "OpenShift"
764+
},
765+
{
766+
"command": "openshift.componentType.newComponent",
767+
"title": "New Component",
768+
"category": "OpenShift"
764769
}
765770
],
766771
"keybindings": [
@@ -1309,11 +1314,18 @@
13091314
},
13101315
{
13111316
"command": "openshift.componentType.openStarterProjectRepository",
1312-
"when": "view == openshiftComponentTypesView && viewItem == s2iImageStreamTag || viewItem == devfileStarterProject"
1317+
"when": "view == openshiftComponentTypesView && viewItem == s2iImageStreamTag || viewItem == devfileStarterProject",
1318+
"group": "1@0"
13131319
},
13141320
{
13151321
"command": "openshift.componentType.cloneStarterProjectRepository",
1316-
"when": "view == openshiftComponentTypesView && viewItem == s2iImageStreamTag || viewItem == devfileStarterProject"
1322+
"when": "view == openshiftComponentTypesView && viewItem == s2iImageStreamTag || viewItem == devfileStarterProject",
1323+
"group": "1@1"
1324+
},
1325+
{
1326+
"command": "openshift.componentType.newComponent",
1327+
"when": "view == openshiftComponentTypesView && viewItem == s2iImageStreamTag || viewItem == devfileStarterProject || viewItem == devfileComponentType",
1328+
"group": "0@0"
13171329
}
13181330
]
13191331
},

src/component.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,25 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
141141
let children: ComponentType[];
142142
if (!parent) {
143143
const result: CliExitData = await this.odo.execute(Command.listCatalogComponentsJson());
144-
children = this.loadItems<ComponentTypesJson, ComponentType>(result, (data) => [...data.s2iItems, ...data.devfileItems]);
144+
children = this.loadItems<ComponentTypesJson, ComponentType>(result, (data) => {
145+
data.s2iItems.forEach((s2iItem) => {
146+
s2iItem.spec.imageStreamTags = s2iItem.spec.imageStreamTags.filter(tag => s2iItem.spec.nonHiddenTags.includes(tag.name));
147+
})
148+
return [...data.s2iItems, ...data.devfileItems]
149+
});
150+
145151
} else if (isS2iComponent(parent)) {
146-
children = parent.spec.imageStreamTags;
152+
children = parent.spec.imageStreamTags.map((tag:ImageStreamTag) => {
153+
tag.typeName = parent.metadata.name;
154+
return tag;
155+
});
147156
} else if (isDevfileComponent(parent)){
148157
const result: CliExitData = await this.odo.execute(Command.describeCatalogComponent(parent.Name));
149158
children = this.loadItems<ComponentTypeDescription, StarterProject>(result, (data) => data.Data.starterProjects);
159+
children = children.map((starter:StarterProject) => {
160+
starter.typeName = parent.Name;;
161+
return starter;
162+
});
150163
}
151164
if (!parent) {
152165
children = children.sort((a, b) => {

src/odo/componentType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum ComponentKind {
1414

1515
export interface ImageStreamTag {
1616
name: string,
17+
typeName?: string;
1718
annotations: {
1819
description: string;
1920
'openshift.io/display-name': string;

src/odo/componentTypeDescription.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface StarterProject {
3838
name: string;
3939
git: Git;
4040
description?: string;
41+
typeName?: string;
4142
}
4243

4344
export interface Git {

src/openshift/component.ts

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { isURL } from 'validator';
1111
import { EventEmitter } from 'events';
1212
import * as YAML from 'yaml'
1313
import OpenShiftItem, { selectTargetApplication, selectTargetComponent } from './openshiftItem';
14-
import { OpenShiftObject, ContextType, OpenShiftObjectImpl, OpenShiftComponent } from '../odo';
14+
import { OpenShiftObject, ContextType, OpenShiftObjectImpl, OpenShiftComponent, OpenShiftApplication } from '../odo';
1515
import { Command } from '../odo/command';
1616
import { Progress } from '../util/progress';
1717
import { CliExitData } from '../cli';
@@ -24,14 +24,15 @@ import LogViewLoader from '../view/log/LogViewLoader';
2424
import DescribeViewLoader from '../view/describe/describeViewLoader';
2525
import { vsCommand, VsCommandError } from '../vscommand';
2626
import { SourceType } from '../odo/config';
27-
import { ComponentKind, ComponentTypeAdapter } from '../odo/componentType';
27+
import { ComponentKind, ComponentTypeAdapter, DevfileComponentType, ImageStreamTag, isDevfileComponent, isImageStreamTag } from '../odo/componentType';
2828
import { Url } from '../odo/url';
2929
import { ComponentDescription, StarterProjectDescription } from '../odo/catalog';
3030
import path = require('path');
3131

3232
import globby = require('globby');
3333
import treeKill = require('tree-kill');
3434
import fs = require('fs-extra');
35+
import { isStarterProject, StarterProject } from '../odo/componentTypeDescription';
3536

3637
const waitPort = require('wait-port');
3738

@@ -106,7 +107,7 @@ export class Component extends OpenShiftItem {
106107
@selectTargetApplication(
107108
'In which Application you want to create a Component'
108109
)
109-
static async create(application: OpenShiftObject): Promise<string> {
110+
static async create(application: OpenShiftApplication): Promise<string> {
110111
if (!application) return null;
111112

112113
const componentSource = await window.showQuickPick(SourceTypeChoice.asArray(), {
@@ -541,16 +542,37 @@ export class Component extends OpenShiftItem {
541542
return JSON.parse(UrlDetails.stdout).items;
542543
}
543544

545+
@vsCommand('openshift.componentType.newComponent')
546+
public static async createComponentFromCatalogEntry(context: DevfileComponentType | StarterProject | ImageStreamTag): Promise<string> {
547+
const application = await Component.getOpenShiftCmdData(undefined,
548+
'Select an Application where you want to create a Component'
549+
);
550+
let componentTypeName: string,
551+
version: string,
552+
starterProjectName:string;
553+
if (isDevfileComponent(context)) {
554+
componentTypeName = context.Name;
555+
} else if (isImageStreamTag(context)) {
556+
componentTypeName = context.typeName;
557+
version = context.name;
558+
} else if (isStarterProject(context)){
559+
componentTypeName = context.typeName;
560+
starterProjectName = context.name;
561+
}
562+
563+
return Component.createFromLocal(application, [], componentTypeName, version, starterProjectName);
564+
}
565+
544566
@vsCommand('openshift.component.createFromLocal')
545567
@selectTargetApplication(
546568
'Select an Application where you want to create a Component'
547569
)
548-
static async createFromLocal(application: OpenShiftObject): Promise<string | null> {
570+
static async createFromLocal(application: OpenShiftApplication, selection?: OpenShiftObject[], componentTypeName?:string, version?:string, starterProjectName?:string): Promise<string | null> {
549571
if (!application) return null;
550572
const workspacePath = await selectWorkspaceFolder();
551573
if (!workspacePath) return null;
552574

553-
return Component.createFromRootWorkspaceFolder(workspacePath, [], application);
575+
return Component.createFromRootWorkspaceFolder(workspacePath, [], application, componentTypeName, version? ComponentKind.S2I : ComponentKind.DEVFILE, version, starterProjectName);
554576
}
555577

556578
/**
@@ -566,15 +588,19 @@ export class Component extends OpenShiftItem {
566588
*/
567589

568590
@vsCommand('openshift.component.createFromRootWorkspaceFolder')
569-
static async createFromRootWorkspaceFolder(folder: Uri, selection: Uri[], context: OpenShiftObject, componentTypeName?: string, componentKind = ComponentKind.DEVFILE): Promise<string | null> {
591+
static async createFromRootWorkspaceFolder(folder: Uri, selection: Uri[], context: OpenShiftApplication, componentTypeName?: string, componentKind = ComponentKind.DEVFILE, version?: string, starterProjectName?: string): Promise<string | null> {
570592

571593
const application = await Component.getOpenShiftCmdData(context,
572594
'Select an Application where you want to create a Component'
573595
);
574596

575597
if (!application) return null;
598+
599+
let useExistingDevfile = false;
576600
const devFileLocation = path.join(folder.fsPath, 'devfile.yaml');
577-
const useExistingDevfile = fs.existsSync(devFileLocation);
601+
if (componentKind === ComponentKind.DEVFILE) {
602+
useExistingDevfile = fs.existsSync(devFileLocation);
603+
}
578604

579605
let initialNameValue: string;
580606
if (useExistingDevfile) {
@@ -597,9 +623,9 @@ export class Component extends OpenShiftItem {
597623
let createStarter: string;
598624
let componentType: ComponentTypeAdapter;
599625
if (!useExistingDevfile) {
600-
const componentTypes = Component.odo.getComponentTypes();
626+
const componentTypes = await Component.odo.getComponentTypes();
601627
if (componentTypeName) {
602-
componentType = (await componentTypes).find(type => type.name === componentTypeName && type.kind === componentKind);
628+
componentType = componentTypes.find(type => type.name === componentTypeName && type.kind === componentKind && (!version || type.version === version));
603629
}
604630
if (!componentType) {
605631
componentType = await window.showQuickPick(componentTypes, { placeHolder: 'Component type', ignoreFocusOut: true });
@@ -611,23 +637,27 @@ export class Component extends OpenShiftItem {
611637
const globbyPath = `${folder.fsPath.replace('\\', '/')}/`;
612638
const paths = globby.sync(`${globbyPath}*`, {dot: true, onlyFiles: false});
613639
if (paths.length === 0) {
614-
const descr = await Component.odo.execute(Command.describeCatalogComponent(componentType.name));
615-
const starterProjects: StarterProjectDescription[] = Component.odo.loadItems<StarterProjectDescription>(descr,(data:{Data:ComponentDescription})=>data.Data.starterProjects);
616-
if(starterProjects?.length && starterProjects?.length > 0) {
617-
const create = await window.showQuickPick(['Yes', 'No'] , {placeHolder: `Initialize Component using ${starterProjects.length === 1 ? '\''.concat(starterProjects[0].name.concat('\' ')) : ''}Starter Project?`});
618-
if (create === 'Yes') {
619-
if (starterProjects.length === 1) {
620-
createStarter = starterProjects[0].name;
621-
} else {
622-
const selectedStarter = await window.showQuickPick(
623-
starterProjects.map(prj => ({label: prj.name, description: prj.description})),
624-
{placeHolder: 'Select Starter Project to initialize Component'}
625-
);
626-
if (!selectedStarter) return null;
627-
createStarter = selectedStarter.label;
640+
if (starterProjectName) {
641+
createStarter = starterProjectName;
642+
} else {
643+
const descr = await Component.odo.execute(Command.describeCatalogComponent(componentType.name));
644+
const starterProjects: StarterProjectDescription[] = Component.odo.loadItems<StarterProjectDescription>(descr,(data:{Data:ComponentDescription})=>data.Data.starterProjects);
645+
if(starterProjects?.length && starterProjects?.length > 0) {
646+
const create = await window.showQuickPick(['Yes', 'No'] , {placeHolder: `Initialize Component using ${starterProjects.length === 1 ? '\''.concat(starterProjects[0].name.concat('\' ')) : ''}Starter Project?`});
647+
if (create === 'Yes') {
648+
if (starterProjects.length === 1) {
649+
createStarter = starterProjects[0].name;
650+
} else {
651+
const selectedStarter = await window.showQuickPick(
652+
starterProjects.map(prj => ({label: prj.name, description: prj.description})),
653+
{placeHolder: 'Select Starter Project to initialize Component'}
654+
);
655+
if (!selectedStarter) return null;
656+
createStarter = selectedStarter.label;
657+
}
658+
} else if (!create) {
659+
return null;
628660
}
629-
} else if (!create) {
630-
return null;
631661
}
632662
}
633663
}
@@ -638,8 +668,8 @@ export class Component extends OpenShiftItem {
638668
`Creating new Component '${componentName}'`,
639669
() => Component.odo.createComponentFromFolder(
640670
application,
641-
componentType? componentType.name : undefined,
642-
componentType? componentType.version : undefined,
671+
componentType.name,
672+
componentType.version,
643673
componentName,
644674
folder,
645675
createStarter,

0 commit comments

Comments
 (0)