diff --git a/package.json b/package.json index cbacfe5..ed7e01d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "microk8s-vscode", - "displayName": "Microk8s", - "description": "Work with the Microk8s local Kubernetes provider in Visual Studio Code", + "displayName": "MicroK8s", + "description": "Work with the MicroK8s local Kubernetes provider in Visual Studio Code", "publisher": "ms-kubernetes-tools", "version": "0.0.1", "engines": { diff --git a/src/microk8s-cloud-provider.ts b/src/microk8s-cloud-provider.ts index 7e380ef..55013cd 100644 --- a/src/microk8s-cloud-provider.ts +++ b/src/microk8s-cloud-provider.ts @@ -2,16 +2,14 @@ import * as vscode from 'vscode'; import * as k8s from 'vscode-kubernetes-tools-api'; import * as microk8s from './microk8s/microk8s'; -import { failed } from './utils/errorable'; -import { shell } from './utils/shell'; class Microk8sCloudProvider implements k8s.CloudExplorerV1.CloudProvider { - readonly cloudName = "Microk8s"; + readonly cloudName = "MicroK8s"; readonly treeDataProvider = new Microk8sTreeDataProvider(); async getKubeconfigYaml(cluster: any): Promise { const treeNode = cluster as Microk8sCloudProviderTreeNode; if (treeNode.nodeType === 'cluster') { - return await getMicrok8sKubeconfigYaml(); + return getMicroK8sKubeconfigYaml(); } return undefined; } @@ -39,7 +37,7 @@ class Microk8sTreeDataProvider implements vscode.TreeDataProvider { - const yaml = await microk8s.getKubeconfig(shell); - if (failed(yaml)) { - if (yaml.error[0].includes('Insufficient permissions')) { - vscode.window.showErrorMessage("Can't get kubeconfig for Microk8s. You need to add yourself to the 'microk8s' group using the command 'sudo usermod -a -G microk8s ' then log out and log in again."); - } else { - vscode.window.showErrorMessage(`Can't get kubeconfig for Microk8s: ${yaml.error[0]}`); - } +function getMicroK8sKubeconfigYaml(): string | undefined { + try { + const originalKubeconfig = microk8s.getKubeconfigYaml(); + const distinctKubeconfig = renameDistinctUser(originalKubeconfig); + return distinctKubeconfig; + } catch (ex) { + vscode.window.showErrorMessage("Can't get kubeconfig for Microk8s. "+ ex.message); return undefined; } - - const originalKubeconfig = yaml.result; - const distinctKubeconfig = renameDistinctUser(originalKubeconfig); - return distinctKubeconfig; } function renameDistinctUser(kubeconfig: string): string { diff --git a/src/microk8s/microk8s.ts b/src/microk8s/microk8s.ts index 0f27bc8..c3145e3 100644 --- a/src/microk8s/microk8s.ts +++ b/src/microk8s/microk8s.ts @@ -1,37 +1,12 @@ import * as vscode from 'vscode'; +import * as fs from 'fs'; // import * as config from '../config/config'; -import { Errorable } from '../utils/errorable'; -import * as shell from '../utils/shell'; -const logChannel = vscode.window.createOutputChannel("Microk8s"); +const logChannel = vscode.window.createOutputChannel("MicroK8s"); -async function invokeObj(sh: shell.Shell, command: string, args: string, opts: shell.ExecOpts, fn: (stdout: string) => T, errfn?: (sr: shell.ShellResult) => Errorable): Promise> { - const bin = /* config.microk8sPath() || */ 'microk8s'; - const cmd = `${bin}.${command} ${args}`; - logChannel.appendLine(`$ ${cmd}`); - return await sh.execObj( - cmd, - `microk8s.${command}`, - opts, - andLog(fn), - errfn - ); -} - -function andLog(fn: (s: string) => T): (s: string) => T { - return (s: string) => { - logChannel.appendLine(s); - return fn(s); - }; -} - -export async function getKubeconfig(sh: shell.Shell): Promise> { - const onError = (sr: shell.ShellResult): Errorable => { - if (sr.stderr && sr.stderr.trim().length > 0) { - return { succeeded: false, error: [sr.stderr] }; - } - return { succeeded: false, error: [sr.stdout] }; // Because Microk8s prints permissions errors to stdout - }; - return invokeObj(sh, `kubectl config view`, ` --raw`, {}, (s) => s, onError); +export function getKubeconfigYaml(): string { + const kubeconfigfile = '/var/snap/microk8s/current/credentials/client.config'; + logChannel.appendLine(`Reading kubeconfig file at ${kubeconfigfile}`); + return fs.readFileSync(kubeconfigfile, 'utf8'); } diff --git a/src/utils/errorable.ts b/src/utils/errorable.ts deleted file mode 100644 index e2f5ba4..0000000 --- a/src/utils/errorable.ts +++ /dev/null @@ -1,26 +0,0 @@ -export interface Succeeded { - readonly succeeded: true; - readonly result: T; -} - -export interface Failed { - readonly succeeded: false; - readonly error: string[]; -} - -export type Errorable = Succeeded | Failed; - -export function succeeded(e: Errorable): e is Succeeded { - return e.succeeded; -} - -export function failed(e: Errorable): e is Failed { - return !e.succeeded; -} - -export function map(e: Errorable, fn: (t: T) => U): Errorable { - if (failed(e)) { - return { succeeded: false, error: e.error }; - } - return { succeeded: true, result: fn(e.result) }; -} diff --git a/src/utils/shell.ts b/src/utils/shell.ts deleted file mode 100644 index 3955b41..0000000 --- a/src/utils/shell.ts +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -import * as shelljs from 'shelljs'; -import * as vscode from 'vscode'; - -import { Errorable } from './errorable'; - -export interface ExecOpts { - readonly cwd?: string; -} - -export interface Shell { - exec(cmd: string, stdin?: string): Promise>; - execObj(cmd: string, cmdDesc: string, opts: ExecOpts, fn: (stdout: string) => T, errfn?: (sr: ShellResult) => Errorable): Promise>; -} - -export const shell: Shell = { - exec: exec, - execObj: execObj, -}; - -export interface ShellResult { - readonly code: number; - readonly stdout: string; - readonly stderr: string; -} - -export type ShellHandler = (code: number, stdout: string, stderr: string) => void; - -function execOpts(): any { - const env = process.env; - const opts = { - cwd: vscode.workspace.rootPath, - env: env, - async: true - }; - return opts; -} - -async function exec(cmd: string, stdin?: string): Promise> { - try { - return { succeeded: true, result: await execCore(cmd, execOpts(), stdin) }; - } catch (ex) { - return { succeeded: false, error: [`Error invoking '${cmd}: ${ex}`] }; - } -} - -async function execObj(cmd: string, cmdDesc: string, opts: ExecOpts, fn: ((stdout: string) => T), errfn?: (sr: ShellResult) => Errorable): Promise> { - const o = Object.assign({}, execOpts(), opts); - try { - const sr = await execCore(cmd, o); - if (sr.code === 0) { - const value = fn(sr.stdout); - return { succeeded: true, result: value }; - } else { - if (errfn) { - return errfn(sr); - } - return { succeeded: false, error: [`${cmdDesc} error: ${sr.stderr}`] }; - } - } catch (ex) { - return { succeeded: false, error: [`Error invoking '${cmd}: ${ex}`] }; - } -} - -function execCore(cmd: string, opts: any, stdin?: string): Promise { - return new Promise((resolve, _reject) => { - const proc = shelljs.exec(cmd, opts, (code, stdout, stderr) => resolve({ code: code, stdout: stdout, stderr: stderr })); - if (stdin) { - proc.stdin.end(stdin); - } - }); -}