mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
more refactorings & fixes on kubeconfig paths
Signed-off-by: Jussi Nummelin <jussi.nummelin@gmail.com>
This commit is contained in:
parent
c46a5f6f20
commit
7178d0534a
@ -1,4 +1,7 @@
|
||||
import { app, remote } from "electron"
|
||||
import ElectronStore from "electron-store"
|
||||
import { ensureDirSync, writeFileSync } from "fs-extra"
|
||||
import * as path from "path"
|
||||
import { Cluster, ClusterBaseInfo } from "../main/cluster";
|
||||
import * as version200Beta2 from "../migrations/cluster-store/2.0.0-beta.2"
|
||||
import * as version241 from "../migrations/cluster-store/2.4.1"
|
||||
@ -117,4 +120,17 @@ export class ClusterStore {
|
||||
}
|
||||
}
|
||||
|
||||
export const clusterStore = ClusterStore.getInstance();
|
||||
export const clusterStore: ClusterStore = ClusterStore.getInstance();
|
||||
|
||||
// Writes kubeconfigs to "embedded" store, i.e. .../Lens/kubeconfigs/
|
||||
export function writeEmbeddedKubeConfig(clusterId: string, kubeConfig: string): string {
|
||||
// This can be called from main & renderer
|
||||
const a = (app || remote.app)
|
||||
const kubeConfigBase = path.join(a.getPath("userData"), "kubeconfigs")
|
||||
ensureDirSync(kubeConfigBase)
|
||||
|
||||
const kubeConfigFile = path.join(kubeConfigBase, clusterId)
|
||||
writeFileSync(kubeConfigFile, kubeConfig)
|
||||
|
||||
return kubeConfigFile
|
||||
}
|
||||
|
||||
@ -86,7 +86,6 @@ export class Cluster implements ClusterInfo {
|
||||
constructor(clusterInfo: ClusterBaseInfo) {
|
||||
if (clusterInfo) Object.assign(this, clusterInfo)
|
||||
if (!this.preferences) this.preferences = {}
|
||||
this.kubeconfigManager = new KubeconfigManager(this)
|
||||
}
|
||||
|
||||
public proxyKubeconfigPath() {
|
||||
@ -95,7 +94,9 @@ export class Cluster implements ClusterInfo {
|
||||
|
||||
public async init(kc: KubeConfig) {
|
||||
this.contextHandler = new ContextHandler(kc, this)
|
||||
//this.contextName = kc.currentContext
|
||||
await this.contextHandler.init() // So we get the proxy port reserved
|
||||
this.kubeconfigManager = new KubeconfigManager(this)
|
||||
|
||||
this.url = this.contextHandler.url
|
||||
this.apiUrl = kc.getCurrentCluster().server
|
||||
}
|
||||
@ -139,14 +140,6 @@ export class Cluster implements ClusterInfo {
|
||||
this.eventCount = await this.getEventCount();
|
||||
}
|
||||
|
||||
// public updateKubeconfig(kubeconfig: string) {
|
||||
// const storedCluster = clusterStore.getCluster(this.id)
|
||||
// if (!storedCluster) { return }
|
||||
|
||||
// this.kubeConfig = kubeconfig
|
||||
// this.save()
|
||||
// }
|
||||
|
||||
public getPrometheusApiPrefix() {
|
||||
if (!this.preferences.prometheus?.prefix) {
|
||||
return ""
|
||||
|
||||
@ -22,14 +22,14 @@ export class ContextHandler {
|
||||
|
||||
protected apiTarget: ServerOptions
|
||||
protected proxyTarget: ServerOptions
|
||||
protected clusterUrl: url.UrlWithStringQuery
|
||||
protected proxyServer: KubeAuthProxy
|
||||
public clusterUrl: url.UrlWithStringQuery
|
||||
public proxyServer: KubeAuthProxy
|
||||
|
||||
protected clientCert: string
|
||||
protected clientKey: string
|
||||
protected secureApiConnection = true
|
||||
protected defaultNamespace: string
|
||||
protected proxyPort: number
|
||||
public proxyPort: number
|
||||
protected kubernetesApi: string
|
||||
protected prometheusProvider: string
|
||||
protected prometheusPath: string
|
||||
@ -38,21 +38,6 @@ export class ContextHandler {
|
||||
constructor(kc: KubeConfig, cluster: Cluster) {
|
||||
this.id = cluster.id
|
||||
this.kc = kc
|
||||
logger.info(`**** ctxHandler.kc: ${JSON.stringify(kc, null, 2)}`)
|
||||
// this.kc.users = [
|
||||
// {
|
||||
// name: kc.getCurrentUser().name,
|
||||
// token: this.id
|
||||
// }
|
||||
// ]
|
||||
// this.kc.contexts = [
|
||||
// {
|
||||
// name: kc.currentContext,
|
||||
// cluster: kc.getCurrentCluster().name,
|
||||
// user: kc.getCurrentUser().name,
|
||||
// namespace: kc.getContextObject(kc.currentContext).namespace
|
||||
// }
|
||||
// ]
|
||||
this.kc.setCurrentContext(cluster.contextName)
|
||||
|
||||
this.cluster = cluster
|
||||
@ -61,16 +46,14 @@ export class ContextHandler {
|
||||
this.defaultNamespace = kc.getContextObject(kc.currentContext).namespace
|
||||
this.url = `http://${this.id}.localhost:${cluster.port}/`
|
||||
this.kubernetesApi = `http://127.0.0.1:${cluster.port}/${this.id}`
|
||||
// this.kc.clusters = [
|
||||
// {
|
||||
// name: kc.getCurrentCluster().name,
|
||||
// server: this.kubernetesApi,
|
||||
// skipTLSVerify: true
|
||||
// }
|
||||
// ]
|
||||
|
||||
this.setClusterPreferences(cluster.preferences)
|
||||
}
|
||||
|
||||
public async init() {
|
||||
await this.resolveProxyPort()
|
||||
}
|
||||
|
||||
public setClusterPreferences(clusterPreferences?: ClusterPreferences) {
|
||||
this.prometheusProvider = clusterPreferences.prometheusProvider?.type
|
||||
|
||||
|
||||
@ -20,19 +20,18 @@ export class KubeconfigManager {
|
||||
return this.tempFile
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new "temporary" kubeconfig that point to the kubectl-proxy.
|
||||
* This way any user of the config does not need to know anything about the auth etc. details.
|
||||
*/
|
||||
protected createTemporaryKubeconfig(): string {
|
||||
ensureDir(this.configDir)
|
||||
const path = `${this.configDir}/${randomFileName("kubeconfig")}`
|
||||
logger.debug('Creating temporary kubeconfig: ' + path)
|
||||
logger.debug(`cluster url: ${this.cluster.url}`)
|
||||
logger.debug(`cluster api url: ${this.cluster.apiUrl}`)
|
||||
|
||||
// TODO Make the names come from actual cluster.name etc.
|
||||
let kc = {
|
||||
clusters: [
|
||||
{
|
||||
name: this.cluster.contextName,
|
||||
server: `http://127.0.0.1:${this.cluster.port}/${this.cluster.id}`
|
||||
server: `http://127.0.0.1:${this.cluster.contextHandler.proxyPort}`
|
||||
}
|
||||
],
|
||||
users: [
|
||||
@ -44,6 +43,7 @@ export class KubeconfigManager {
|
||||
{
|
||||
name: this.cluster.contextName,
|
||||
cluster: this.cluster.contextName,
|
||||
namespace: this.cluster.contextHandler.kc.getContextObject(this.cluster.contextName).namespace,
|
||||
user: "proxy"
|
||||
}
|
||||
],
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
import { app } from "electron"
|
||||
import { ensureDirSync, writeFileSync } from "fs-extra"
|
||||
import * as path from "path"
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
import * as clusterStore from "../../cluster-store"
|
||||
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 3.5.0-beta.1");
|
||||
@ -11,21 +13,23 @@ export function migration(store: any) {
|
||||
ensureDirSync(kubeConfigBase)
|
||||
let storedClusters = store.get("clusters") as any[]
|
||||
if (!storedClusters) return
|
||||
|
||||
|
||||
console.log("num clusters to migrate: ", storedClusters.length)
|
||||
for (let cluster of storedClusters ) {
|
||||
// TODO Should probably guard this, not to make the whole migration fail if one cluster fails!?
|
||||
// take the embedded kubeconfig and dump it into a file
|
||||
const kubeConfigFile = path.join(kubeConfigBase, cluster.id)
|
||||
writeFileSync(kubeConfigFile, cluster.kubeConfig)
|
||||
delete cluster.kubeConfig
|
||||
const kubeConfigFile = clusterStore.writeEmbeddedKubeConfig(cluster.id, cluster.kubeConfig)
|
||||
cluster.kubeConfigPath = kubeConfigFile
|
||||
// TODO Need to parse the context name from the config
|
||||
|
||||
|
||||
// "overwrite" the cluster configs
|
||||
|
||||
const kc = new KubeConfig()
|
||||
kc.loadFromFile(cluster.kubeConfigPath)
|
||||
cluster.contextName = kc.getCurrentContext()
|
||||
|
||||
delete cluster.kubeConfig
|
||||
clusters.push(cluster)
|
||||
}
|
||||
|
||||
// "overwrite" the cluster configs
|
||||
if (clusters.length > 0) {
|
||||
store.set("clusters", clusters)
|
||||
}
|
||||
|
||||
@ -10,6 +10,15 @@
|
||||
<b-form-group
|
||||
label="Choose config:"
|
||||
>
|
||||
<b-form-file
|
||||
v-model="file"
|
||||
:state="Boolean(file)"
|
||||
placeholder="Choose a file or drop it here..."
|
||||
drop-placeholder="Drop file here..."
|
||||
@input="reloadKubeContexts()"
|
||||
></b-form-file>
|
||||
<div class="mt-3">Selected file: {{ file ? file.name : '' }}</div>
|
||||
|
||||
<b-form-select
|
||||
id="kubecontext-select"
|
||||
v-model="kubecontext"
|
||||
@ -114,6 +123,9 @@ import * as k8s from "@kubernetes/client-node"
|
||||
import { dumpConfigYaml } from "../../../main/k8s"
|
||||
import ClustersMixin from "@/_vue/mixins/ClustersMixin";
|
||||
import * as path from "path"
|
||||
import fs from 'fs'
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import * as clusterStore from "../../common/cluster-store"
|
||||
|
||||
class ClusterAccessError extends Error {}
|
||||
|
||||
@ -126,6 +138,8 @@ export default {
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
file: null,
|
||||
filepath: null,
|
||||
clusterconfig: "",
|
||||
httpsProxy: "",
|
||||
kubecontext: "",
|
||||
@ -137,7 +151,10 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
this.$store.dispatch("reloadAvailableKubeContexts");
|
||||
const kubeConfigPath = path.join(process.env.HOME, '.kube', 'config')
|
||||
this.filepath = kubeConfigPath
|
||||
this.file = new File(fs.readFileSync(this.filepath), this.filepath)
|
||||
this.$store.dispatch("reloadAvailableKubeContexts", this.filepath);
|
||||
this.seenContexts = JSON.parse(JSON.stringify(this.$store.getters.seenContexts)) // clone seenContexts from store
|
||||
this.storeSeenContexts()
|
||||
},
|
||||
@ -164,6 +181,10 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
reloadKubeContexts() {
|
||||
this.filepath = this.file.path
|
||||
this.$store.dispatch("reloadAvailableKubeContexts", this.file.path);
|
||||
},
|
||||
isNewContext(context) {
|
||||
return this.newContexts.indexOf(context) > -1
|
||||
},
|
||||
@ -197,12 +218,15 @@ export default {
|
||||
try {
|
||||
const kc = new k8s.KubeConfig();
|
||||
kc.loadFromString(this.clusterconfig); // throws TypeError if we cannot parse kubeconfig
|
||||
|
||||
// TODO Remove hardcoded path
|
||||
const configPath = path.join(process.env.HOME, '.kube', 'config');
|
||||
|
||||
const clusterId = uuidv4();
|
||||
// We need to store the kubeconfig to "app-home"/
|
||||
if (this.kubecontext === "custom") {
|
||||
// TODO Call "writeEmbeddedKubeConfig"
|
||||
this.filepath = clusterStore.writeEmbeddedKubeConfig(clusterId, this.clusterconfig)
|
||||
}
|
||||
const clusterInfo = {
|
||||
kubeConfigPath: configPath,
|
||||
id: clusterId,
|
||||
kubeConfigPath: this.filepath,
|
||||
contextName: kc.currentContext,
|
||||
preferences: {
|
||||
clusterName: kc.currentContext
|
||||
@ -212,6 +236,7 @@ export default {
|
||||
if (this.httpsProxy) {
|
||||
clusterInfo.preferences.httpsProxy = this.httpsProxy
|
||||
}
|
||||
console.log("sending clusterInfo:", clusterInfo)
|
||||
let res = await this.$store.dispatch('addCluster', clusterInfo)
|
||||
console.log("addCluster result:", res)
|
||||
if(!res){
|
||||
|
||||
@ -6,10 +6,10 @@ const state = {
|
||||
}
|
||||
|
||||
const actions = {
|
||||
reloadAvailableKubeContexts: ({commit}) => {
|
||||
reloadAvailableKubeContexts({commit}, file) {
|
||||
let kc = new k8s.KubeConfig();
|
||||
try {
|
||||
kc.loadFromDefault();
|
||||
kc.loadFromFile(file);
|
||||
} catch (error) {
|
||||
console.error("Failed to read default kubeconfig: " + error.message);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user