Single + bulk download kubeconfig

This commit is contained in:
Vincent Fiduccia 2021-05-11 12:41:24 -07:00
parent 8f15575514
commit ecfed78021
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
4 changed files with 170 additions and 50 deletions

View File

@ -75,9 +75,10 @@ nav:
title: Dashboard
backToRancher: Cluster Manager
clusterTools: Cluster Tools
shell: Kubectl Shell
kubeconfig: Download KubeConfig
import: Import YAML
home: Home
shell: Kubectl Shell
support: Get Support
group:
cluster: Cluster

View File

@ -47,11 +47,15 @@ export default {
return this.$store.getters['rancher/byId'](NORMAN.PRINCIPAL, this.$store.getters['auth/principalId']) || {};
},
showShell() {
kubeConfigEnabled() {
return true;
},
shellEnabled() {
return !!this.currentCluster?.links?.shell;
},
showImport() {
importEnabled() {
return !!this.currentCluster?.actions?.apply;
},
@ -147,36 +151,46 @@ export default {
</div>
<div v-if="!simple" class="header-buttons">
<button
v-if="currentProduct && currentProduct.showClusterSwitcher"
v-tooltip="t('nav.import')"
:disabled="!showImport"
type="button"
class="btn header-btn role-tertiary"
@click="openImport()"
>
<i class="icon icon-upload icon-lg" />
</button>
<modal
class="import-modal"
name="importModal"
width="75%"
height="auto"
styles="max-height: 90vh;"
>
<Import :cluster="currentCluster" @close="closeImport" />
</modal>
<template v-if="currentProduct && currentProduct.showClusterSwitcher">
<button
v-tooltip="t('nav.import')"
:disabled="!importEnabled"
type="button"
class="btn header-btn role-tertiary"
@click="openImport()"
>
<i class="icon icon-upload icon-lg" />
</button>
<modal
class="import-modal"
name="importModal"
width="75%"
height="auto"
styles="max-height: 90vh;"
>
<Import :cluster="currentCluster" @close="closeImport" />
</modal>
<button
v-if="currentProduct && currentProduct.showClusterSwitcher"
v-tooltip="t('nav.shell')"
:disabled="!showShell"
type="button"
class="btn header-btn role-tertiary"
@click="currentCluster.openShell()"
>
<i class="icon icon-terminal icon-lg" />
</button>
<button
v-tooltip="t('nav.shell')"
:disabled="!shellEnabled"
type="button"
class="btn header-btn role-tertiary"
@click="currentCluster.openShell()"
>
<i class="icon icon-terminal icon-lg" />
</button>
<button
v-tooltip="t('nav.kubeconfig')"
:disabled="!kubeConfigEnabled"
type="button"
class="btn header-btn role-tertiary"
@click="currentCluster.downloadKubeConfig()"
>
<i class="icon icon-file icon-lg" />
</button>
</template>
<button
v-if="showSearch"

View File

@ -1,7 +1,10 @@
import { CATALOG } from '@/config/labels-annotations';
import { FLEET, MANAGEMENT } from '@/config/types';
import { insertAt } from '@/utils/array';
import { downloadFile } from '@/utils/download';
import { parseSi } from '@/utils/units';
import jsyaml from 'js-yaml';
import { eachLimit } from '@/utils/promise';
// See translation file cluster.providers for list of providers
// If the logo is not named with the provider name, add an override here
@ -37,6 +40,15 @@ export default {
enabled: !!this.links.shell,
});
insertAt(out, 1, {
action: 'downloadKubeConfig',
bulkAction: 'downloadKubeConfigBulk',
label: 'Download KubeConfig',
icon: 'icon icon-download',
bulkable: true,
enabled: this.$rootGetters['isRancher'],
});
return out;
},
@ -102,21 +114,6 @@ export default {
return '';
},
openShell() {
return () => {
this.$dispatch('wm/open', {
id: `kubectl-${ this.id }`,
label: this.$rootGetters['i18n/t']('wm.kubectlShell.title', { name: this.nameDisplay }),
icon: 'terminal',
component: 'KubectlShell',
attrs: {
cluster: this,
pod: {}
}
}, { root: true });
};
},
providerOs() {
if ( this.status?.provider === 'rke.windows' ) {
return 'windows';
@ -189,5 +186,67 @@ export default {
} else {
return null;
}
}
},
openShell() {
return () => {
this.$dispatch('wm/open', {
id: `kubectl-${ this.id }`,
label: this.$rootGetters['i18n/t']('wm.kubectlShell.title', { name: this.nameDisplay }),
icon: 'terminal',
component: 'KubectlShell',
attrs: {
cluster: this,
pod: {}
}
}, { root: true });
};
},
generateKubeConfig() {
return async() => {
const res = await this.$dispatch('request', {
method: 'post',
url: `/v3/clusters/${ this.id }?action=generateKubeconfig`
});
return res.config;
};
},
downloadKubeConfig() {
return async() => {
const config = await this.generateKubeConfig();
downloadFile(`${ this.nameDisplay }.yaml`, config, 'application/yaml');
};
},
downloadKubeConfigBulk() {
return async(items) => {
let obj = {};
let first = true;
await eachLimit(items, 10, (item, idx) => {
return item.generateKubeConfig().then((config) => {
const entry = jsyaml.safeLoad(config);
if ( first ) {
obj = entry;
first = false;
} else {
obj.clusters.push(...entry.clusters);
obj.users.push(...entry.users);
obj.contexts.push(...entry.contexts);
}
});
});
delete obj['current-context'];
const out = jsyaml.safeDump(obj);
downloadFile('kubeconfig.yaml', out, 'application/yaml');
};
},
};

View File

@ -1,5 +1,5 @@
import { CAPI, MANAGEMENT, NORMAN } from '@/config/types';
import { findBy } from '@/utils/array';
import { findBy, insertAt } from '@/utils/array';
import { sortBy } from '@/utils/sort';
import { ucFirst } from '@/utils/string';
@ -25,6 +25,28 @@ export default {
return out;
},
_availableActions() {
const out = this._standardActions;
insertAt(out, 0, {
action: 'openShell',
label: 'Kubectl Shell',
icon: 'icon icon-terminal',
enabled: !!this.mgmt?.links.shell,
});
insertAt(out, 1, {
action: 'downloadKubeConfig',
bulkAction: 'downloadKubeConfigBulk',
label: 'Download KubeConfig',
icon: 'icon icon-download',
bulkable: true,
enabled: this.$rootGetters['isRancher'],
});
return out;
},
isImported() {
return this.provisioner === 'imported';
},
@ -208,5 +230,29 @@ export default {
return token.save();
};
}
},
openShell() {
return () => {
return this.mgmt?.openShell();
};
},
generateKubeConfig() {
return () => {
return this.mgmt?.generateKubeConfig();
};
},
downloadKubeConfig() {
return () => {
return this.mgmt?.downloadKubeConfig();
};
},
downloadKubeConfigBulk() {
return (items) => {
return this.mgmt?.downloadKubeConfigBulk(items);
};
},
};