/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); import { Kubectl } from './kubectl'; import { failed, ClusterType } from '../interfaces'; export interface KubectlContext { readonly clusterName: string; readonly contextName: string; readonly userName: string; readonly active: boolean; } interface Kubeconfig { readonly apiVersion: string; readonly 'current-context': string; readonly clusters: { readonly name: string; readonly cluster: { readonly server: string; readonly 'certificate-authority'?: string; readonly 'certificate-authority-data'?: string; }; }[] | undefined; readonly contexts: { readonly name: string; readonly context: { readonly cluster: string; readonly user: string; readonly namespace?: string; }; }[] | undefined; readonly users: { readonly name: string; readonly user: {}; }[] | undefined; } export interface ClusterConfig { readonly server: string; readonly certificateAuthority: string | undefined; } async function getKubeconfig(kubectl: Kubectl): Promise { const shellResult = await kubectl.asJson('config view -o json'); if (failed(shellResult)) { vscode.window.showErrorMessage(shellResult.error[0]); return null; } return shellResult.result; } export async function getCurrentClusterConfig(kubectl: Kubectl): Promise { const kubeConfig = await getKubeconfig(kubectl); if (!kubeConfig || !kubeConfig.clusters || !kubeConfig.contexts) { return undefined; } const contextConfig = kubeConfig.contexts.find((context) => context.name === kubeConfig['current-context'])!; const clusterConfig = kubeConfig.clusters.find((cluster) => cluster.name === contextConfig.context.cluster)!; return { server: clusterConfig.cluster.server, certificateAuthority: clusterConfig.cluster['certificate-authority'] }; } export async function getContexts(kubectl: Kubectl): Promise { const kubectlConfig = await getKubeconfig(kubectl); if (!kubectlConfig) { return []; } const currentContext = kubectlConfig['current-context']; const contexts = kubectlConfig.contexts || []; return contexts.map((c) => { return { clusterName: c.context.cluster, contextName: c.name, userName: c.context.user, active: c.name === currentContext }; }); } export async function setContext(kubectl: Kubectl, targetContext: string): Promise { const shellResult = await kubectl.invokeAsync(`config use-context ${targetContext}`); if (!shellResult || shellResult.code !== 0) { // TODO: Update error handling for now. let errMsg = shellResult ? shellResult.stderr : localize('runKubectlFailed', 'Unable to run kubectl'); vscode.window.showErrorMessage(localize('setClusterFailed', 'Failed to set \'{0}\' as current cluster: {1}', targetContext, errMsg)); } } export async function inferCurrentClusterType(kubectl: Kubectl): Promise { let latestContextName = ''; const ctxsr = await kubectl.invokeAsync('config current-context'); if (ctxsr && ctxsr.code === 0) { latestContextName = ctxsr.stdout.trim(); } else { return ClusterType.Other; } const cisr = await kubectl.invokeAsync('cluster-info'); if (!cisr || cisr.code !== 0) { return ClusterType.Unknown; } const masterInfos = cisr.stdout.split('\n') .filter((s) => s.indexOf('master is running at') >= 0); if (masterInfos.length === 0) { return ClusterType.Other; } const masterInfo = masterInfos[0]; if (masterInfo.indexOf('azmk8s.io') >= 0 || masterInfo.indexOf('azure.com') >= 0) { return ClusterType.AKS; } if (latestContextName) { const gcsr = await kubectl.invokeAsync(`config get-contexts ${latestContextName}`); if (gcsr && gcsr.code === 0) { if (gcsr.stdout.indexOf('minikube') >= 0) { return ClusterType.Minikube; } } } return ClusterType.Other; }