1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-09 15:55:23 +02:00

feature(kubeconfig): access to all kube environment contexts from within the Portainer UI [EE-1727] (#5966)

This commit is contained in:
Marcelo Rydel 2021-11-22 11:05:09 -07:00 committed by GitHub
parent c0a4727114
commit 6be1ff4d9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 404 additions and 434 deletions

View file

@ -1,4 +1,5 @@
import _ from 'lodash-es';
import { PortainerEndpointTypes } from '@/portainer/models/endpoint/models';
const ENDPOINTS_POLLING_INTERVAL = 30000; // in ms
const ENDPOINTS_CACHE_SIZE = 100;
@ -6,8 +7,10 @@ const ENDPOINTS_CACHE_SIZE = 100;
angular.module('portainer.app').controller('EndpointListController', [
'DatatableService',
'PaginationService',
'ModalService',
'KubernetesConfigService',
'Notifications',
function EndpointListController(DatatableService, PaginationService, Notifications) {
function EndpointListController(DatatableService, PaginationService, ModalService, KubernetesConfigService, Notifications) {
this.state = {
totalFilteredEndpoints: null,
textFilter: '',
@ -126,6 +129,50 @@ angular.module('portainer.app').controller('EndpointListController', [
return status === 1 ? 'up' : 'down';
}
this.showKubeconfigButton = function () {
if (window.location.protocol !== 'https:') {
return false;
}
return _.some(this.endpoints, (endpoint) => isKubernetesMode(endpoint));
};
function isKubernetesMode(endpoint) {
return [
PortainerEndpointTypes.KubernetesLocalEnvironment,
PortainerEndpointTypes.AgentOnKubernetesEnvironment,
PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment,
].includes(endpoint.Type);
}
this.showKubeconfigModal = async function () {
const kubeEnvironments = _.filter(this.endpoints, (endpoint) => isKubernetesMode(endpoint));
const options = kubeEnvironments.map(function (environment) {
return {
text: `${environment.Name} (${environment.URL})`,
value: environment.Id,
};
});
let expiryMessage = '';
try {
expiryMessage = await KubernetesConfigService.expiryMessage();
} catch (e) {
Notifications.error('Failed fetching kubeconfig expiry time', e);
}
ModalService.confirmKubeconfigSelection(options, expiryMessage, async function (selectedEnvironmentIDs) {
if (selectedEnvironmentIDs.length === 0) {
Notifications.warning('No environment was selected');
return;
}
try {
await KubernetesConfigService.downloadKubeconfigFile(selectedEnvironmentIDs);
} catch (e) {
Notifications.error('Failed downloading kubeconfig file', e);
}
});
};
this.$onInit = function () {
var textFilter = DatatableService.getDataTableTextFilters(this.tableKey);
this.state.paginatedItemLimit = PaginationService.getPaginationLimit(this.tableKey);

View file

@ -12,6 +12,17 @@
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.snapshotAction()" data-cy="home-refreshEndpointsButton">
<i class="fa fa-sync space-right" aria-hidden="true"></i>Refresh
</button>
<button
ng-if="$ctrl.showKubeconfigButton()"
type="button"
class="btn btn-sm btn-primary"
ng-click="$ctrl.showKubeconfigModal()"
analytics-on
analytics-category="kubernetes"
analytics-event="kubernetes-kubectl-kubeconfig-multi"
>
<i class="fas fa-download space-right"></i> kubeconfig
</button>
</div>
<div class="searchBar">

View file

@ -82,17 +82,20 @@ angular.module('portainer.app').factory('ModalService', [
applyBoxCSS(box);
}
function customPrompt(options, optionToggled) {
function customCheckboxPrompt(options) {
var box = bootbox.prompt({
title: options.title,
inputType: options.inputType,
inputType: 'checkbox',
inputOptions: options.inputOptions,
buttons: confirmButtons(options),
callback: options.callback,
});
applyBoxCSS(box);
box.find('.bootbox-body').prepend('<p>' + options.message + '</p>');
box.find('.bootbox-input-checkbox').prop('checked', optionToggled);
box.find('.bootbox-input-checkbox').prop('checked', options.optionToggled);
if (options.showCheck) {
box.find('.bootbox-input-checkbox').addClass('visible');
}
}
service.confirmAccessControlUpdate = function (callback) {
@ -231,28 +234,25 @@ angular.module('portainer.app').factory('ModalService', [
};
service.confirmContainerRecreation = function (callback) {
customPrompt(
{
title: 'Are you sure?',
message:
"You're about to re-create this container, any non-persisted data will be lost. This container will be removed and another one will be created using the same configuration.",
inputType: 'checkbox',
inputOptions: [
{
text: 'Pull latest image<i></i>',
value: '1',
},
],
buttons: {
confirm: {
label: 'Recreate',
className: 'btn-danger',
},
customCheckboxPrompt({
title: 'Are you sure?',
message:
"You're about to re-create this container, any non-persisted data will be lost. This container will be removed and another one will be created using the same configuration.",
inputOptions: [
{
text: 'Pull latest image<i></i>',
value: '1',
},
],
buttons: {
confirm: {
label: 'Recreate',
className: 'btn-danger',
},
callback: callback,
},
false
);
callback: callback,
optionToggled: false,
});
};
service.confirmEndpointSnapshot = function (callback) {
@ -285,27 +285,24 @@ angular.module('portainer.app').factory('ModalService', [
service.confirmServiceForceUpdate = function (message, callback) {
message = $sanitize(message);
customPrompt(
{
title: 'Are you sure ?',
message: message,
inputType: 'checkbox',
inputOptions: [
{
text: 'Pull latest image version<i></i>',
value: '1',
},
],
buttons: {
confirm: {
label: 'Update',
className: 'btn-primary',
},
customCheckboxPrompt({
title: 'Are you sure ?',
message: message,
inputOptions: [
{
text: 'Pull latest image version<i></i>',
value: '1',
},
],
buttons: {
confirm: {
label: 'Update',
className: 'btn-primary',
},
callback: callback,
},
false
);
callback: callback,
optionToggled: false,
});
};
service.selectRegistry = function (options) {
@ -319,6 +316,24 @@ angular.module('portainer.app').factory('ModalService', [
applyBoxCSS(box);
};
service.confirmKubeconfigSelection = function (options, expiryMessage, callback) {
const message = 'Select the kubernetes environment(s) to add to the kubeconfig file.</br>' + expiryMessage;
customCheckboxPrompt({
title: 'Download kubeconfig file',
message: $sanitize(message),
inputOptions: options,
buttons: {
confirm: {
label: 'Download file',
className: 'btn-primary',
},
},
callback: callback,
optionToggled: true,
showCheck: true,
});
};
return service;
},
]);