Skip to content

Commit

Permalink
Provide fake kubeconfig for Components View to work without one
Browse files Browse the repository at this point in the history
This PR fixes redhat-developer#2044.

Signed-off-by: Denis Golovin dgolovin@redhat.com
  • Loading branch information
dgolovin committed May 3, 2021
1 parent 31f644e commit dd43057
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 9 deletions.
15 changes: 15 additions & 0 deletions config/kubeconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://api.crc.testing:6443
name: api-crc-testing:6443
contexts:
- context:
cluster: api-crc-testing:6443
user: developer
name: no-config-workaround
current-context: no-config-workaround
preferences: {}
users:
- name: developer
File renamed without changes.
7 changes: 4 additions & 3 deletions src/componentTypesView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
import { vsCommand, VsCommandError } from './vscommand';
import { Cluster } from '@kubernetes/client-node/dist/config_types';
import { KubeConfig } from '@kubernetes/client-node';
import { Platform } from './util/platform';

type ExampleProject = SampleProject | StarterProject;
type ComponentType = DevfileComponentType | ImageStreamTag | ExampleProject | Cluster | Registry;
Expand Down Expand Up @@ -191,7 +192,7 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
// eslint-disable-next-line class-methods-use-this
async getChildren(parent: ComponentType): Promise<ComponentType[]> {
let children: ComponentType[];

const addEnv = this.odo.getKubeconfigEnv();
if (!parent) {
const config = new KubeConfig();
config.loadFromDefault();
Expand All @@ -211,7 +212,7 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
children = [];
builders.forEach((builder: S2iComponentType) => children.splice(children.length,0, ...builder.spec.imageStreamTags));
} else if (isRegistry(parent) ) {
const result: CliExitData = await this.odo.execute(Command.listCatalogComponentsJson());
const result = await this.odo.execute(Command.listCatalogComponentsJson(),Platform.getUserHomePath(), true, addEnv);
children = this.loadItems<ComponentTypesJson, DevfileComponentType>(result, (data) => data.devfileItems);
children = children.filter((element:DevfileComponentType) => element.Registry.Name === parent.Name);
} else if (isS2iComponent(parent)) {
Expand All @@ -220,7 +221,7 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
return tag;
});
} else if (isDevfileComponent(parent)){
const result: CliExitData = await this.odo.execute(Command.describeCatalogComponent(parent.Name));
const result: CliExitData = await this.odo.execute(Command.describeCatalogComponent(parent.Name), Platform.getUserHomePath(), true, addEnv);
children = this.loadItems<ComponentTypeDescription, StarterProject>(result, (data) => data.Data.starterProjects);
children = children.map((starter:StarterProject) => {
starter.typeName = parent.Name;;
Expand Down
35 changes: 30 additions & 5 deletions src/odo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import { VsCommandError } from './vscommand';
import { Storage } from './odo/storage';
import bs = require('binary-search');
import { CliExitData } from './cli';
import { KubeConfigUtils } from './util/kubeUtils';
import { KubeConfig } from '@kubernetes/client-node';
import { pathExistsSync } from 'fs-extra';

const {Collapsed} = TreeItemCollapsibleState;

Expand Down Expand Up @@ -329,6 +332,7 @@ class OdoEventImpl implements OdoEvent {
}

export interface Odo {
getKubeconfigEnv(): {};
getClusters(): Promise<OpenShiftObject[]>;
getProjects(): Promise<OpenShiftObject[]>;
loadWorkspaceComponents(event: WorkspaceFoldersChangeEvent): Promise<void>;
Expand All @@ -344,7 +348,7 @@ export interface Odo {
getServiceTemplates(): Promise<string[]>;
getServiceTemplatePlans(svc: string): Promise<string[]>;
getServices(application: OpenShiftObject): Promise<OpenShiftObject[]>;
execute(command: CommandText, cwd?: string, fail?: boolean): Promise<cliInstance.CliExitData>;
execute(command: CommandText, cwd?: string, fail?: boolean, addEnv?: {}): Promise<cliInstance.CliExitData>;
spawn(command: string, cwd?: string): Promise<ChildProcess>;
executeInTerminal(command: CommandText, cwd?: string, name?: string): Promise<void>;
requireLogin(): Promise<boolean>;
Expand Down Expand Up @@ -616,8 +620,29 @@ export class OdoImpl implements Odo {
return deployedComponents;
}

public getKubeconfigEnv(): {} {
const addEnv: {KUBECONFIG?: string} = {};
let kc: KubeConfig;
// TODO: Remove when odo works without kubeconfig present
try {
kc = new KubeConfigUtils();
} catch (err) {
// ignore error
}

const configPath = path.join(Platform.getUserHomePath(), '.kube', 'config');

if (kc && !pathExistsSync(configPath)) { // config is loaded, yay! But there is still use case for missing config file
// use fake config to let odo get component types from registry
addEnv.KUBECONFIG = path.resolve(__dirname, '..', '..', 'config', 'kubeconfig');
}
return addEnv;
}

public async getComponentTypes(): Promise<ComponentType[]> {
const result: cliInstance.CliExitData = await this.execute(Command.listCatalogComponentsJson());
// if kc is produced, KUBECONFIG env var is empty or pointing

const result: cliInstance.CliExitData = await this.execute(Command.listCatalogComponentsJson(), undefined, true, this.getKubeconfigEnv());
const compTypesJson: ComponentTypesJson = this.loadJSON(result.stdout);
const devfileItems: ComponentTypeAdapter[] = [];
const s2iItems: ComponentTypeAdapter[] = [];
Expand Down Expand Up @@ -738,7 +763,7 @@ export class OdoImpl implements Odo {

public createEnv(): {} {
const env = {...process.env };
env.GLOBALODOCONFIG = path.resolve(__dirname,'..', '..', 'preference.yaml');
env.GLOBALODOCONFIG = path.resolve(__dirname,'..', '..', 'config', 'preference.yaml');
return env;
}

Expand All @@ -750,15 +775,15 @@ export class OdoImpl implements Odo {
terminal.show();
}

public async execute(command: CommandText, cwd?: string, fail = true): Promise<cliInstance.CliExitData> {
public async execute(command: CommandText, cwd?: string, fail = true, addEnv = {}): Promise<cliInstance.CliExitData> {
const env = this.createEnv();
const commandActual = `${command}`;
const commandPrivacy = `${command.privacyMode(true)}`;
const [cmd] = commandActual.split(' ');
const toolLocation = await ToolsConfig.detect(cmd);
const result: cliInstance.CliExitData = await OdoImpl.cli.execute(
toolLocation ? commandActual.replace(cmd, `"${toolLocation}"`) : commandActual,
cwd ? {cwd, env} : { env }
cwd ? {cwd, env: {...env, ...addEnv}} : { env: {...env, ...addEnv} }
);
if (result.error && fail) {
throw new VsCommandError(`${result.error.message}`, `Error when running command: ${commandPrivacy}`, result.error);
Expand Down
2 changes: 1 addition & 1 deletion src/odo/componentType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function isSampleProject(repo: any): repo is SampleProject {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isCluster(cluster: any): cluster is Cluster {
return cluster.name && cluster.server && cluster.skipTLSVerify !== undefined;
return cluster.name && cluster.server;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down

0 comments on commit dd43057

Please sign in to comment.