From 3da9751c823e97f2faabde5de95daebd007a4aa9 Mon Sep 17 00:00:00 2001 From: xAt0mZ Date: Mon, 26 Oct 2020 19:34:07 +0100 Subject: [PATCH 001/157] feat(k8s/applications): add pod as new application type for apps list --- .../applicationsDatatable.html | 9 ++++--- .../applicationsDatatableController.js | 3 ++- app/kubernetes/converters/application.js | 25 ++++++++++++++---- app/kubernetes/filters/applicationFilters.js | 2 ++ app/kubernetes/helpers/application/index.js | 4 +-- .../helpers/application/rollback.js | 2 +- app/kubernetes/helpers/history/index.js | 2 +- app/kubernetes/helpers/serviceHelper.js | 3 +++ .../horizontal-pod-auto-scaler/helper.js | 3 ++- .../models/application/models/constants.js | 2 ++ app/kubernetes/models/common/params.js | 11 +++----- app/kubernetes/pod/service.js | 26 ++++++++++++++++--- app/kubernetes/services/applicationService.js | 23 +++++++++++++--- app/kubernetes/services/historyService.js | 14 ++++++---- .../init/endpoint/initEndpointController.js | 2 +- 15 files changed, 96 insertions(+), 35 deletions(-) diff --git a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html index 5d0ece02c..e90ef8362 100644 --- a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html +++ b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html @@ -151,11 +151,14 @@ >{{ item.Image }} + {{ item.Containers.length - 1 }} {{ item.ApplicationType | kubernetesApplicationTypeText }} - + Replicated Global - {{ item.RunningPodsCount }} / {{ item.TotalPodsCount }} + {{ item.RunningPodsCount }} / {{ item.TotalPodsCount }} + + + {{ item.Pods[0].Status }} + diff --git a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js index aaee33363..f195c2bc0 100644 --- a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js +++ b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js @@ -1,4 +1,4 @@ -import { KubernetesApplicationDeploymentTypes } from 'Kubernetes/models/application/models'; +import { KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models'; import KubernetesApplicationHelper from 'Kubernetes/helpers/application'; angular.module('portainer.docker').controller('KubernetesApplicationsDatatableController', [ @@ -42,6 +42,7 @@ angular.module('portainer.docker').controller('KubernetesApplicationsDatatableCo this.$onInit = function () { this.isAdmin = Authentication.isAdmin(); this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes; + this.KubernetesApplicationTypes = KubernetesApplicationTypes; this.setDefaults(); this.prepareTableFromDataset(); diff --git a/app/kubernetes/converters/application.js b/app/kubernetes/converters/application.js index 56cfdf2bb..8e603cdf0 100644 --- a/app/kubernetes/converters/application.js +++ b/app/kubernetes/converters/application.js @@ -50,7 +50,7 @@ function _apiPortsToPublishedPorts(pList, pRefs) { class KubernetesApplicationConverter { static applicationCommon(res, data, pods, service, ingresses) { - const containers = _.without(_.concat(data.spec.template.spec.containers, data.spec.template.spec.initContainers), undefined); + const containers = data.spec.template ? _.without(_.concat(data.spec.template.spec.containers, data.spec.template.spec.initContainers), undefined) : data.spec.containers; res.Id = data.metadata.uid; res.Name = data.metadata.name; res.StackName = data.metadata.labels ? data.metadata.labels[KubernetesPortainerApplicationStackNameLabel] || '-' : '-'; @@ -61,7 +61,7 @@ class KubernetesApplicationConverter { res.Image = containers[0].image; res.CreationDate = data.metadata.creationTimestamp; res.Env = _.without(_.flatMap(_.map(containers, 'env')), undefined); - res.Pods = KubernetesApplicationHelper.associatePodsAndApplication(pods, data); + res.Pods = data.spec.selector ? KubernetesApplicationHelper.associatePodsAndApplication(pods, data.spec.selector) : [data]; const limits = { Cpu: 0, @@ -118,7 +118,11 @@ class KubernetesApplicationConverter { res.PublishedPorts = ports; } - res.Volumes = data.spec.template.spec.volumes ? data.spec.template.spec.volumes : []; + if (data.spec.templates) { + res.Volumes = data.spec.template.spec.volumes ? data.spec.template.spec.volumes : []; + } else { + res.Volumes = data.spec.volumes; + } // TODO: review // this if() fixs direct use of PVC reference inside spec.template.spec.containers[0].volumeMounts @@ -169,7 +173,7 @@ class KubernetesApplicationConverter { res.PersistedFolders = _.without(res.PersistedFolders, undefined); res.ConfigurationVolumes = _.reduce( - data.spec.template.spec.volumes, + res.Volumes, (acc, volume) => { if (volume.configMap || volume.secret) { const matchingVolumeMount = _.find(_.flatMap(_.map(containers, 'volumeMounts')), { name: volume.name }); @@ -213,6 +217,17 @@ class KubernetesApplicationConverter { ); } + static apiPodToApplication(data, pods, service, ingresses) { + const res = new KubernetesApplication(); + KubernetesApplicationConverter.applicationCommon(res, data, pods, service, ingresses); + res.ApplicationType = KubernetesApplicationTypes.POD; + // res.DeploymentType = KubernetesApplicationDeploymentTypes.REPLICATED; + // res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.SHARED; + // res.RunningPodsCount = data.status.availableReplicas || data.status.replicas - data.status.unavailableReplicas || 0; + // res.TotalPodsCount = data.spec.replicas; + return res; + } + static apiDeploymentToApplication(data, pods, service, ingresses) { const res = new KubernetesApplication(); KubernetesApplicationConverter.applicationCommon(res, data, pods, service, ingresses); @@ -310,7 +325,7 @@ class KubernetesApplicationConverter { } else if (daemonSet) { app = KubernetesDaemonSetConverter.applicationFormValuesToDaemonSet(formValues, claims); } else { - throw new PortainerError('Unable to determine which association to use'); + throw new PortainerError('Unable to determine which association to use to convert form'); } let headlessService; diff --git a/app/kubernetes/filters/applicationFilters.js b/app/kubernetes/filters/applicationFilters.js index 0629c12ff..0ce2d3831 100644 --- a/app/kubernetes/filters/applicationFilters.js +++ b/app/kubernetes/filters/applicationFilters.js @@ -57,6 +57,8 @@ angular return KubernetesApplicationTypeStrings.DAEMONSET; case KubernetesApplicationTypes.STATEFULSET: return KubernetesApplicationTypeStrings.STATEFULSET; + case KubernetesApplicationTypes.POD: + return KubernetesApplicationTypeStrings.POD; default: return '-'; } diff --git a/app/kubernetes/helpers/application/index.js b/app/kubernetes/helpers/application/index.js index 9bc898fca..3124f4247 100644 --- a/app/kubernetes/helpers/application/index.js +++ b/app/kubernetes/helpers/application/index.js @@ -38,8 +38,8 @@ class KubernetesApplicationHelper { return !application.ApplicationOwner; } - static associatePodsAndApplication(pods, app) { - return _.filter(pods, { Labels: app.spec.selector.matchLabels }); + static associatePodsAndApplication(pods, selector) { + return _.filter(pods, ['metadata.labels', selector.matchLabels]); } static associateContainerPersistedFoldersAndConfigurations(app, containers) { diff --git a/app/kubernetes/helpers/application/rollback.js b/app/kubernetes/helpers/application/rollback.js index f593e0cf5..7f110e8f8 100644 --- a/app/kubernetes/helpers/application/rollback.js +++ b/app/kubernetes/helpers/application/rollback.js @@ -20,7 +20,7 @@ class KubernetesApplicationRollbackHelper { result = KubernetesApplicationRollbackHelper._getStatefulSetPayload(application, targetRevision); break; default: - throw new PortainerError('Unable to determine which association to use'); + throw new PortainerError('Unable to determine which association to use to convert patch'); } return result; } diff --git a/app/kubernetes/helpers/history/index.js b/app/kubernetes/helpers/history/index.js index d611644a0..5f8851ab4 100644 --- a/app/kubernetes/helpers/history/index.js +++ b/app/kubernetes/helpers/history/index.js @@ -21,7 +21,7 @@ class KubernetesHistoryHelper { [currentRevision, revisionsList] = KubernetesHistoryHelper._getStatefulSetRevisions(rawRevisions, application.Raw); break; default: - throw new PortainerError('Unable to determine which association to use'); + throw new PortainerError('Unable to determine which association to use to get revisions'); } revisionsList = _.sortBy(revisionsList, 'revision'); return [currentRevision, revisionsList]; diff --git a/app/kubernetes/helpers/serviceHelper.js b/app/kubernetes/helpers/serviceHelper.js index c263a3766..247e4a441 100644 --- a/app/kubernetes/helpers/serviceHelper.js +++ b/app/kubernetes/helpers/serviceHelper.js @@ -7,6 +7,9 @@ class KubernetesServiceHelper { } static findApplicationBoundService(services, rawApp) { + if (!rawApp.spec.template) { + return undefined; + } return _.find(services, (item) => item.spec.selector && _.isMatch(rawApp.spec.template.metadata.labels, item.spec.selector)); } } diff --git a/app/kubernetes/horizontal-pod-auto-scaler/helper.js b/app/kubernetes/horizontal-pod-auto-scaler/helper.js index 663c3baf8..44bc10c49 100644 --- a/app/kubernetes/horizontal-pod-auto-scaler/helper.js +++ b/app/kubernetes/horizontal-pod-auto-scaler/helper.js @@ -18,7 +18,8 @@ export class KubernetesHorizontalPodAutoScalerHelper { return KubernetesApplicationTypeStrings.DAEMONSET; } else if ((app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.STATEFULSET) || app instanceof KubernetesStatefulSet) { return KubernetesApplicationTypeStrings.STATEFULSET; - // } else if () { ---> TODO: refactor - handle bare pod type ! + } else if (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.POD) { + return KubernetesApplicationTypeStrings.POD; } else { throw new PortainerError('Unable to determine application type'); } diff --git a/app/kubernetes/models/application/models/constants.js b/app/kubernetes/models/application/models/constants.js index 2d42bba05..970cb3557 100644 --- a/app/kubernetes/models/application/models/constants.js +++ b/app/kubernetes/models/application/models/constants.js @@ -12,12 +12,14 @@ export const KubernetesApplicationTypes = Object.freeze({ DEPLOYMENT: 1, DAEMONSET: 2, STATEFULSET: 3, + POD: 4, }); export const KubernetesApplicationTypeStrings = Object.freeze({ DEPLOYMENT: 'Deployment', DAEMONSET: 'DaemonSet', STATEFULSET: 'StatefulSet', + POD: 'Pod', }); export const KubernetesApplicationPublishingTypes = Object.freeze({ diff --git a/app/kubernetes/models/common/params.js b/app/kubernetes/models/common/params.js index fd37b8764..5c7de8d34 100644 --- a/app/kubernetes/models/common/params.js +++ b/app/kubernetes/models/common/params.js @@ -1,11 +1,8 @@ /** * Generic params */ -const _KubernetesCommonParams = Object.freeze({ - id: '', -}); -export class KubernetesCommonParams { - constructor() { - Object.assign(this, JSON.parse(JSON.stringify(_KubernetesCommonParams))); - } +export function KubernetesCommonParams() { + return { + id: '', + }; } diff --git a/app/kubernetes/pod/service.js b/app/kubernetes/pod/service.js index c2de34a2e..2aa3df981 100644 --- a/app/kubernetes/pod/service.js +++ b/app/kubernetes/pod/service.js @@ -1,9 +1,7 @@ -import _ from 'lodash-es'; import angular from 'angular'; import PortainerError from 'Portainer/error'; import { KubernetesCommonParams } from 'Kubernetes/models/common/params'; -import KubernetesPodConverter from 'Kubernetes/pod/converter'; class KubernetesPodService { /* @ngInject */ @@ -11,23 +9,43 @@ class KubernetesPodService { this.$async = $async; this.KubernetesPods = KubernetesPods; + this.getAsync = this.getAsync.bind(this); this.getAllAsync = this.getAllAsync.bind(this); this.logsAsync = this.logsAsync.bind(this); this.deleteAsync = this.deleteAsync.bind(this); } + + async getAsync(namespace, name) { + try { + const params = new KubernetesCommonParams(); + params.id = name; + const [raw, yaml] = await Promise.all([this.KubernetesPods(namespace).get(params).$promise, this.KubernetesPods(namespace).getYaml(params).$promise]); + const res = { + Raw: raw, + Yaml: yaml.data, + }; + return res; + } catch (err) { + throw new PortainerError('Unable to retrieve pod', err); + } + } + /** * GET ALL */ async getAllAsync(namespace) { try { const data = await this.KubernetesPods(namespace).get().$promise; - return _.map(data.items, (item) => KubernetesPodConverter.apiToModel(item)); + return data.items; } catch (err) { throw new PortainerError('Unable to retrieve pods', err); } } - get(namespace) { + get(namespace, name) { + if (name) { + return this.$async(this.getAsync, namespace, name); + } return this.$async(this.getAllAsync, namespace); } diff --git a/app/kubernetes/services/applicationService.js b/app/kubernetes/services/applicationService.js index 55bfa9908..075adb91f 100644 --- a/app/kubernetes/services/applicationService.js +++ b/app/kubernetes/services/applicationService.js @@ -18,6 +18,7 @@ import KubernetesServiceHelper from 'Kubernetes/helpers/serviceHelper'; import { KubernetesHorizontalPodAutoScalerHelper } from 'Kubernetes/horizontal-pod-auto-scaler/helper'; import { KubernetesHorizontalPodAutoScalerConverter } from 'Kubernetes/horizontal-pod-auto-scaler/converter'; import { KubernetesIngressConverter } from 'Kubernetes/ingress/converter'; +import KubernetesPodConverter from 'Kubernetes/pod/converter'; class KubernetesApplicationService { /* #region CONSTRUCTOR */ @@ -71,7 +72,7 @@ class KubernetesApplicationService { } else if (app instanceof KubernetesStatefulSet || (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.STATEFULSET)) { apiService = this.KubernetesStatefulSetService; } else { - throw new PortainerError('Unable to determine which association to use'); + throw new PortainerError('Unable to determine which association to use to retrieve API Service'); } return apiService; } @@ -87,15 +88,18 @@ class KubernetesApplicationService { /* #region GET */ async getAsync(namespace, name) { try { - const [deployment, daemonSet, statefulSet, pods, autoScalers, ingresses] = await Promise.allSettled([ + const [deployment, daemonSet, statefulSet, pod, pods, autoScalers, ingresses] = await Promise.allSettled([ this.KubernetesDeploymentService.get(namespace, name), this.KubernetesDaemonSetService.get(namespace, name), this.KubernetesStatefulSetService.get(namespace, name), + this.KubernetesPodService.get(namespace, name), this.KubernetesPodService.get(namespace), this.KubernetesHorizontalPodAutoScalerService.get(namespace), this.KubernetesIngressService.get(namespace), ]); + // const pod = _.find(pods.value, ['metadata.namespace', namespace, 'metadata.name', name]); + let rootItem; let converterFunc; if (deployment.status === 'fulfilled') { @@ -107,8 +111,11 @@ class KubernetesApplicationService { } else if (statefulSet.status === 'fulfilled') { rootItem = statefulSet; converterFunc = KubernetesApplicationConverter.apiStatefulSetToapplication; + } else if (pod.status === 'fulfilled') { + rootItem = pod; + converterFunc = KubernetesApplicationConverter.apiPodToApplication; } else { - throw new PortainerError('Unable to determine which association to use'); + throw new PortainerError('Unable to determine which association to use to convert application'); } const services = await this.KubernetesServiceService.get(namespace); @@ -118,6 +125,7 @@ class KubernetesApplicationService { const application = converterFunc(rootItem.value.Raw, pods.value, service.Raw, ingresses.value); application.Yaml = rootItem.value.Yaml; application.Raw = rootItem.value.Raw; + application.Pods = _.map(application.Pods, (item) => KubernetesPodConverter.apiToModel(item)); application.Containers = KubernetesApplicationHelper.associateContainersAndApplication(application); const boundScaler = KubernetesHorizontalPodAutoScalerHelper.findApplicationBoundScaler(autoScalers.value, application); @@ -173,7 +181,14 @@ class KubernetesApplicationService { convertToApplication(item, KubernetesApplicationConverter.apiStatefulSetToapplication, services, pods, ingresses) ); - const applications = _.concat(deploymentApplications, daemonSetApplications, statefulSetApplications); + const boundPods = _.concat(_.flatMap(deploymentApplications, 'Pods'), _.flatMap(daemonSetApplications, 'Pods'), _.flatMap(statefulSetApplications, 'Pods')); + const unboundPods = _.without(pods, ...boundPods); + const nakedPodsApplications = _.map(unboundPods, (item) => convertToApplication(item, KubernetesApplicationConverter.apiPodToApplication, services, pods, ingresses)); + + const applications = _.concat(deploymentApplications, daemonSetApplications, statefulSetApplications, nakedPodsApplications); + _.forEach(applications, (app) => { + app.Pods = _.map(app.Pods, (item) => KubernetesPodConverter.apiToModel(item)); + }); await Promise.all( _.forEach(applications, async (application) => { const boundScaler = KubernetesHorizontalPodAutoScalerHelper.findApplicationBoundScaler(autoScalers, application); diff --git a/app/kubernetes/services/historyService.js b/app/kubernetes/services/historyService.js index df0284166..b00bf7f3e 100644 --- a/app/kubernetes/services/historyService.js +++ b/app/kubernetes/services/historyService.js @@ -32,13 +32,17 @@ class KubernetesHistoryService { case KubernetesApplicationTypes.STATEFULSET: rawRevisions = await this.KubernetesControllerRevisionService.get(namespace); break; + case KubernetesApplicationTypes.POD: + rawRevisions = []; + break; default: - throw new PortainerError('Unable to determine which association to use'); + throw new PortainerError('Unable to determine which association to use for history'); + } + if (rawRevisions.length) { + const [currentRevision, revisionsList] = KubernetesHistoryHelper.getRevisions(rawRevisions, application); + application.CurrentRevision = currentRevision; + application.Revisions = revisionsList; } - - const [currentRevision, revisionsList] = KubernetesHistoryHelper.getRevisions(rawRevisions, application); - application.CurrentRevision = currentRevision; - application.Revisions = revisionsList; return application; } catch (err) { throw new PortainerError('', err); diff --git a/app/portainer/views/init/endpoint/initEndpointController.js b/app/portainer/views/init/endpoint/initEndpointController.js index 15a2faa87..c5a39a737 100644 --- a/app/portainer/views/init/endpoint/initEndpointController.js +++ b/app/portainer/views/init/endpoint/initEndpointController.js @@ -61,7 +61,7 @@ class InitEndpointController { case PortainerEndpointConnectionTypes.AGENT: return this.createAgentEndpoint(); default: - this.Notifications.error('Failure', 'Unable to determine which action to do'); + this.Notifications.error('Failure', 'Unable to determine which action to do to create endpoint'); } } From 174e28b850aa3ef0cade6d27e1b9baeb71de7828 Mon Sep 17 00:00:00 2001 From: xAt0mZ Date: Mon, 26 Oct 2020 19:47:23 +0100 Subject: [PATCH 002/157] feat(k8s/application): app details for pods --- .../containers-datatable/containersDatatable.html | 4 ++-- .../containers-datatable/containersDatatable.js | 1 + app/kubernetes/converters/application.js | 4 ---- .../views/applications/edit/application.html | 12 +++++++++--- .../views/applications/edit/applicationController.js | 5 +++-- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/kubernetes/components/datatables/application/containers-datatable/containersDatatable.html b/app/kubernetes/components/datatables/application/containers-datatable/containersDatatable.html index 8c291971d..1d77ab609 100644 --- a/app/kubernetes/components/datatables/application/containers-datatable/containersDatatable.html +++ b/app/kubernetes/components/datatables/application/containers-datatable/containersDatatable.html @@ -57,7 +57,7 @@ - + - + diff --git a/app/portainer/components/datatables/roles-datatable/rolesDatatable.html b/app/portainer/components/datatables/roles-datatable/rolesDatatable.html new file mode 100644 index 000000000..107e08fb6 --- /dev/null +++ b/app/portainer/components/datatables/roles-datatable/rolesDatatable.html @@ -0,0 +1,64 @@ +
+ + +
+
{{ $ctrl.titleText }}
+
+ +
+
+ Pod @@ -107,7 +107,7 @@ dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))" pagination-id="$ctrl.tableKey" > - {{ item.PodName }}{{ item.PodName }} {{ item.Name }} {{ item.Image }}
Status + Replicated Global {{ ctrl.application.RunningPodsCount }} / {{ ctrl.application.TotalPodsCount }} + {{ ctrl.application.Pods[0].Status }} +
Resource reservations
-
per instance
+
+ per instance +
CPU {{ ctrl.application.Requests.Cpu | kubernetesApplicationCPUValue }}
@@ -557,7 +562,8 @@ title-icon="fa-server" dataset="ctrl.allContainers" table-key="kubernetes.application.containers" - order-by="PodName" + is-pod="ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD" + order-by="{{ ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD ? 'Name' : 'PodName' }}" > diff --git a/app/kubernetes/views/applications/edit/applicationController.js b/app/kubernetes/views/applications/edit/applicationController.js index b3304df8c..773e2099c 100644 --- a/app/kubernetes/views/applications/edit/applicationController.js +++ b/app/kubernetes/views/applications/edit/applicationController.js @@ -1,7 +1,7 @@ import angular from 'angular'; import * as _ from 'lodash-es'; import * as JsonPatch from 'fast-json-patch'; -import { KubernetesApplicationDataAccessPolicies, KubernetesApplicationDeploymentTypes } from 'Kubernetes/models/application/models'; +import { KubernetesApplicationDataAccessPolicies, KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models'; import KubernetesEventHelper from 'Kubernetes/helpers/eventHelper'; import KubernetesApplicationHelper from 'Kubernetes/helpers/application'; import { KubernetesServiceTypes } from 'Kubernetes/models/service/models'; @@ -123,6 +123,8 @@ class KubernetesApplicationController { this.KubernetesNamespaceHelper = KubernetesNamespaceHelper; + this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes; + this.KubernetesApplicationTypes = KubernetesApplicationTypes; this.ApplicationDataAccessPolicies = KubernetesApplicationDataAccessPolicies; this.KubernetesServiceTypes = KubernetesServiceTypes; this.KubernetesPodContainerTypes = KubernetesPodContainerTypes; @@ -340,7 +342,6 @@ class KubernetesApplicationController { SelectedRevision: undefined, }; - this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes; await this.getApplication(); await this.getEvents(); this.state.viewReady = true; From a12f2ee8933f844cf32df9f552e22ecd427a081d Mon Sep 17 00:00:00 2001 From: Mulia Nasution Date: Wed, 28 Oct 2020 05:33:23 +0700 Subject: [PATCH 003/157] Fix typo, change Matamo to Matomo (#4409) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 010c8ffa1..9d300a082 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ For community support: You can find more information about Portainer's community ## Privacy -**To make sure we focus our development effort in the right places we need to know which features get used most often. To give us this information we use [Matamo Analytics](https://matomo.org/), which is hosted in Germany and is fully GDPR compliant.** +**To make sure we focus our development effort in the right places we need to know which features get used most often. To give us this information we use [Matomo Analytics](https://matomo.org/), which is hosted in Germany and is fully GDPR compliant.** When Portainer first starts, you are given the option to DISABLE analytics. If you **don't** choose to disable it, we collect anonymous usage as per [our privacy policy](https://www.portainer.io/documentation/in-app-analytics-and-privacy-policy/). **Please note**, there is no personally identifiable information sent or stored at any time and we only use the data to help us improve Portainer. From 1545a42f083bf0836a03603f9b985c161aab12a0 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Tue, 3 Nov 2020 06:16:18 +1300 Subject: [PATCH 004/157] chore(github): update bug report template Update documentation URLs --- .github/ISSUE_TEMPLATE/Bug_report.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 00b13e087..3e9b69019 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -16,7 +16,7 @@ already open. You can ensure this by searching the issue list for this repository. If there is a duplicate, please close your issue and add a comment to the existing issue instead. -Also, be sure to check our FAQ and documentation first: https://portainer.readthedocs.io +Also, be sure to check our FAQ and documentation first: https://documentation.portainer.io/ --> **Bug description** @@ -27,7 +27,7 @@ A clear and concise description of what you expected to happen. **Portainer Logs** Provide the logs of your Portainer container or Service. -You can see how [here](https://portainer.readthedocs.io/en/stable/faq.html#how-do-i-get-the-logs-from-portainer) +You can see how [here](https://documentation.portainer.io/archive/1.23.2/faq/#how-do-i-get-the-logs-from-portainer) **Steps to reproduce the issue:** From 0d20988befe34a64fddc63635782e8f704bec046 Mon Sep 17 00:00:00 2001 From: Alice Groux Date: Thu, 5 Nov 2020 08:49:37 +0100 Subject: [PATCH 005/157] fix(rest): remove timeouts for all REST services (#4385) --- app/docker/rest/container.js | 4 ---- app/docker/rest/image.js | 2 +- app/docker/rest/network.js | 1 - app/docker/rest/service.js | 1 - app/docker/rest/system.js | 3 +-- app/docker/rest/task.js | 1 - app/docker/rest/volume.js | 2 +- app/integrations/storidge/rest/storidge.js | 4 ++-- app/kubernetes/component-status/rest.js | 1 - app/kubernetes/endpoint/rest.js | 1 - app/kubernetes/horizontal-pod-auto-scaler/rest.js | 1 - app/kubernetes/ingress/rest.js | 1 - app/kubernetes/node/rest.js | 1 - app/kubernetes/rest/configMap.js | 1 - app/kubernetes/rest/controllerRevision.js | 1 - app/kubernetes/rest/daemonSet.js | 1 - app/kubernetes/rest/deployment.js | 1 - app/kubernetes/rest/endpoint.js | 1 - app/kubernetes/rest/event.js | 1 - app/kubernetes/rest/health.js | 2 +- app/kubernetes/rest/namespace.js | 1 - app/kubernetes/rest/persistentVolumeClaim.js | 1 - app/kubernetes/rest/pod.js | 1 - app/kubernetes/rest/replicaSet.js | 1 - app/kubernetes/rest/resourceQuota.js | 1 - app/kubernetes/rest/secret.js | 1 - app/kubernetes/rest/service.js | 1 - app/kubernetes/rest/statefulSet.js | 1 - app/kubernetes/rest/storage.js | 1 - 29 files changed, 6 insertions(+), 34 deletions(-) diff --git a/app/docker/rest/container.js b/app/docker/rest/container.js index aae286f11..203d16201 100644 --- a/app/docker/rest/container.js +++ b/app/docker/rest/container.js @@ -19,7 +19,6 @@ angular.module('portainer.docker').factory('Container', [ params: { all: 0, action: 'json', filters: '@filters' }, isArray: true, interceptor: ContainersInterceptor, - timeout: 15000, }, get: { method: 'GET', @@ -48,20 +47,17 @@ angular.module('portainer.docker').factory('Container', [ logs: { method: 'GET', params: { id: '@id', action: 'logs' }, - timeout: 4500, ignoreLoadingBar: true, transformResponse: logsHandler, }, stats: { method: 'GET', params: { id: '@id', stream: false, action: 'stats' }, - timeout: 4500, ignoreLoadingBar: true, }, top: { method: 'GET', params: { id: '@id', action: 'top' }, - timeout: 4500, ignoreLoadingBar: true, }, start: { diff --git a/app/docker/rest/image.js b/app/docker/rest/image.js index aa0d8a6a9..c1dbb9f90 100644 --- a/app/docker/rest/image.js +++ b/app/docker/rest/image.js @@ -16,7 +16,7 @@ angular.module('portainer.docker').factory('Image', [ endpointId: EndpointProvider.endpointID, }, { - query: { method: 'GET', params: { all: 0, action: 'json' }, isArray: true, interceptor: ImagesInterceptor, timeout: 15000 }, + query: { method: 'GET', params: { all: 0, action: 'json' }, isArray: true, interceptor: ImagesInterceptor }, get: { method: 'GET', params: { action: 'json' } }, search: { method: 'GET', params: { action: 'search' } }, history: { method: 'GET', params: { action: 'history' }, isArray: true }, diff --git a/app/docker/rest/network.js b/app/docker/rest/network.js index 8c8480158..eb92ccdf6 100644 --- a/app/docker/rest/network.js +++ b/app/docker/rest/network.js @@ -18,7 +18,6 @@ angular.module('portainer.docker').factory('Network', [ method: 'GET', isArray: true, interceptor: NetworksInterceptor, - timeout: 15000, }, get: { method: 'GET', diff --git a/app/docker/rest/service.js b/app/docker/rest/service.js index aecd4acbe..d852e98c4 100644 --- a/app/docker/rest/service.js +++ b/app/docker/rest/service.js @@ -35,7 +35,6 @@ angular.module('portainer.docker').factory('Service', [ logs: { method: 'GET', params: { id: '@id', action: 'logs' }, - timeout: 4500, ignoreLoadingBar: true, transformResponse: logsHandler, }, diff --git a/app/docker/rest/system.js b/app/docker/rest/system.js index fa69df952..917146c4f 100644 --- a/app/docker/rest/system.js +++ b/app/docker/rest/system.js @@ -18,10 +18,9 @@ angular.module('portainer.docker').factory('System', [ info: { method: 'GET', params: { action: 'info' }, - timeout: 15000, interceptor: InfoInterceptor, }, - version: { method: 'GET', params: { action: 'version' }, timeout: 4500, interceptor: VersionInterceptor }, + version: { method: 'GET', params: { action: 'version' }, interceptor: VersionInterceptor }, events: { method: 'GET', params: { action: 'events', since: '@since', until: '@until' }, diff --git a/app/docker/rest/task.js b/app/docker/rest/task.js index e2fa19603..dd818b861 100644 --- a/app/docker/rest/task.js +++ b/app/docker/rest/task.js @@ -17,7 +17,6 @@ angular.module('portainer.docker').factory('Task', [ logs: { method: 'GET', params: { id: '@id', action: 'logs' }, - timeout: 4500, ignoreLoadingBar: true, transformResponse: logsHandler, }, diff --git a/app/docker/rest/volume.js b/app/docker/rest/volume.js index dd35f793b..76941ea5a 100644 --- a/app/docker/rest/volume.js +++ b/app/docker/rest/volume.js @@ -18,7 +18,7 @@ angular.module('portainer.docker').factory('Volume', [ endpointId: EndpointProvider.endpointID, }, { - query: { method: 'GET', interceptor: VolumesInterceptor, timeout: 15000 }, + query: { method: 'GET', interceptor: VolumesInterceptor }, get: { method: 'GET', params: { id: '@id' } }, create: { method: 'POST', diff --git a/app/integrations/storidge/rest/storidge.js b/app/integrations/storidge/rest/storidge.js index 7e46d89d4..83a9b107c 100644 --- a/app/integrations/storidge/rest/storidge.js +++ b/app/integrations/storidge/rest/storidge.js @@ -12,9 +12,9 @@ angular.module('portainer.integrations.storidge').factory('Storidge', [ { rebootCluster: { method: 'POST', params: { resource: 'clusters', action: 'reboot' } }, shutdownCluster: { method: 'POST', params: { resource: 'clusters', action: 'shutdown' } }, - queryEvents: { method: 'GET', params: { resource: 'clusters', action: 'events' }, timeout: 4500, ignoreLoadingBar: true, isArray: true }, + queryEvents: { method: 'GET', params: { resource: 'clusters', action: 'events' }, ignoreLoadingBar: true, isArray: true }, getVersion: { method: 'GET', params: { resource: 'clusters', action: 'version' } }, - getInfo: { method: 'GET', params: { resource: 'clusters', action: 'info' }, timeout: 4500, ignoreLoadingBar: true }, + getInfo: { method: 'GET', params: { resource: 'clusters', action: 'info' }, ignoreLoadingBar: true }, queryNodes: { method: 'GET', params: { resource: 'nodes' } }, getNode: { method: 'GET', params: { resource: 'nodes', id: '@id' } }, diff --git a/app/kubernetes/component-status/rest.js b/app/kubernetes/component-status/rest.js index a286b584f..1e27343ed 100644 --- a/app/kubernetes/component-status/rest.js +++ b/app/kubernetes/component-status/rest.js @@ -14,7 +14,6 @@ angular.module('portainer.kubernetes').factory('KubernetesComponentStatus', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, } diff --git a/app/kubernetes/endpoint/rest.js b/app/kubernetes/endpoint/rest.js index 9728d0414..68cf483ee 100644 --- a/app/kubernetes/endpoint/rest.js +++ b/app/kubernetes/endpoint/rest.js @@ -15,7 +15,6 @@ angular.module('portainer.kubernetes').factory('KubernetesEndpoints', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, } diff --git a/app/kubernetes/horizontal-pod-auto-scaler/rest.js b/app/kubernetes/horizontal-pod-auto-scaler/rest.js index a6cdc4cb1..a0500ada1 100644 --- a/app/kubernetes/horizontal-pod-auto-scaler/rest.js +++ b/app/kubernetes/horizontal-pod-auto-scaler/rest.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesHorizontalPodAutoScale { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/ingress/rest.js b/app/kubernetes/ingress/rest.js index 98f2eea97..df335653b 100644 --- a/app/kubernetes/ingress/rest.js +++ b/app/kubernetes/ingress/rest.js @@ -15,7 +15,6 @@ function factory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) { { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/node/rest.js b/app/kubernetes/node/rest.js index a145ae017..cbb804216 100644 --- a/app/kubernetes/node/rest.js +++ b/app/kubernetes/node/rest.js @@ -16,7 +16,6 @@ angular.module('portainer.kubernetes').factory('KubernetesNodes', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/configMap.js b/app/kubernetes/rest/configMap.js index 62ad844dd..4b8772d18 100644 --- a/app/kubernetes/rest/configMap.js +++ b/app/kubernetes/rest/configMap.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesConfigMaps', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/controllerRevision.js b/app/kubernetes/rest/controllerRevision.js index fb8892c32..cd1cdd193 100644 --- a/app/kubernetes/rest/controllerRevision.js +++ b/app/kubernetes/rest/controllerRevision.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesControllerRevisions', { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/daemonSet.js b/app/kubernetes/rest/daemonSet.js index f2cfa025d..6019cb4d3 100644 --- a/app/kubernetes/rest/daemonSet.js +++ b/app/kubernetes/rest/daemonSet.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesDaemonSets', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/deployment.js b/app/kubernetes/rest/deployment.js index 44b2eb662..99439f665 100644 --- a/app/kubernetes/rest/deployment.js +++ b/app/kubernetes/rest/deployment.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesDeployments', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/endpoint.js b/app/kubernetes/rest/endpoint.js index 7fce22e41..71fde10b4 100644 --- a/app/kubernetes/rest/endpoint.js +++ b/app/kubernetes/rest/endpoint.js @@ -11,7 +11,6 @@ angular.module('portainer.kubernetes').factory('KubernetesEndpoints', function K { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, } diff --git a/app/kubernetes/rest/event.js b/app/kubernetes/rest/event.js index 54f9b07a5..15393bf05 100644 --- a/app/kubernetes/rest/event.js +++ b/app/kubernetes/rest/event.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesEvents', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/health.js b/app/kubernetes/rest/health.js index cbfe3be73..bc41be4f3 100644 --- a/app/kubernetes/rest/health.js +++ b/app/kubernetes/rest/health.js @@ -7,7 +7,7 @@ angular.module('portainer.kubernetes').factory('KubernetesHealth', [ API_ENDPOINT_ENDPOINTS + '/:id/kubernetes/healthz', {}, { - ping: { method: 'GET', timeout: 15000, params: { id: 'id' } }, + ping: { method: 'GET', params: { id: 'id' } }, } ); }, diff --git a/app/kubernetes/rest/namespace.js b/app/kubernetes/rest/namespace.js index 843893d58..482ca4132 100644 --- a/app/kubernetes/rest/namespace.js +++ b/app/kubernetes/rest/namespace.js @@ -16,7 +16,6 @@ angular.module('portainer.kubernetes').factory('KubernetesNamespaces', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/persistentVolumeClaim.js b/app/kubernetes/rest/persistentVolumeClaim.js index 25dd65177..e19529430 100644 --- a/app/kubernetes/rest/persistentVolumeClaim.js +++ b/app/kubernetes/rest/persistentVolumeClaim.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesPersistentVolumeClaims { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/pod.js b/app/kubernetes/rest/pod.js index 2726eadd3..000068e9c 100644 --- a/app/kubernetes/rest/pod.js +++ b/app/kubernetes/rest/pod.js @@ -18,7 +18,6 @@ angular.module('portainer.kubernetes').factory('KubernetesPods', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/replicaSet.js b/app/kubernetes/rest/replicaSet.js index 45dbf6c2c..29b0440c6 100644 --- a/app/kubernetes/rest/replicaSet.js +++ b/app/kubernetes/rest/replicaSet.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesReplicaSets', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/resourceQuota.js b/app/kubernetes/rest/resourceQuota.js index c1eae1036..a2bf9e8c2 100644 --- a/app/kubernetes/rest/resourceQuota.js +++ b/app/kubernetes/rest/resourceQuota.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesResourceQuotas', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/secret.js b/app/kubernetes/rest/secret.js index 1767871aa..6595ce5d4 100644 --- a/app/kubernetes/rest/secret.js +++ b/app/kubernetes/rest/secret.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesSecrets', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/service.js b/app/kubernetes/rest/service.js index c483f13f2..1cbe21e75 100644 --- a/app/kubernetes/rest/service.js +++ b/app/kubernetes/rest/service.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesServices', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/statefulSet.js b/app/kubernetes/rest/statefulSet.js index 3fa962aa0..50551b87a 100644 --- a/app/kubernetes/rest/statefulSet.js +++ b/app/kubernetes/rest/statefulSet.js @@ -17,7 +17,6 @@ angular.module('portainer.kubernetes').factory('KubernetesStatefulSets', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { diff --git a/app/kubernetes/rest/storage.js b/app/kubernetes/rest/storage.js index d3ef80d68..4a79439a5 100644 --- a/app/kubernetes/rest/storage.js +++ b/app/kubernetes/rest/storage.js @@ -16,7 +16,6 @@ angular.module('portainer.kubernetes').factory('KubernetesStorage', [ { get: { method: 'GET', - timeout: 15000, ignoreLoadingBar: true, }, getYaml: { From 9136ba30ebea3040f0bf562aa292e02e4dd42e01 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Wed, 2 Dec 2020 08:27:30 +1300 Subject: [PATCH 006/157] feat(build-system): update pull-dog configuration (#4532) * feat(build-system): update pull-dog configuration * feat(build): update pull-dog configuration --- docker-compose.pull-dog.yml | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/docker-compose.pull-dog.yml b/docker-compose.pull-dog.yml index 76e571a83..e080d7714 100644 --- a/docker-compose.pull-dog.yml +++ b/docker-compose.pull-dog.yml @@ -12,5 +12,48 @@ services: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data + swarm: + image: docker:dind + privileged: true + restart: always + volumes: + - /tmp/manager_run:/var/run + + swarm-init: + image: docker:dind + privileged: true + command: + - /bin/sh + - -c + - | + apk add curl + curl -L https://raw.githubusercontent.com/eficode/wait-for/master/wait-for -o /bin/wait-for + chmod +x /bin/wait-for + wait-for swarm:2376 -- docker -H unix://swarm/run/docker.sock swarm init + docker -H unix://swarm/run/docker.sock swarm init + docker -H unix://swarm/run/docker.sock network create --driver overlay portainer_agent_network + docker -H unix://swarm/run/docker.sock service create -q --name portainer_agent --network portainer_agent_network --publish mode=host,target=9001,published=9001 -e AGENT_CLUSTER_ADDR=tasks.portainer_agent --mode global --mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock --mount type=bind,src=//var/lib/docker/volumes,dst=/var/lib/docker/volumes --mount type=bind,src=/,dst=/host portainer/agent + depends_on: + - swarm + volumes: + - /tmp/manager_run:/swarm/run + + kube: + image: portainer/kube-tools:latest + privileged: true + command: + - /bin/bash + - -c + - | + service docker start + sleep 3 + kind create cluster --config=/kind.yaml + curl -L https://raw.githubusercontent.com/portainer/k8s/master/deploy/manifests/agent/portainer-agent-k8s-nodeport.yaml -o portainer-agent.yaml + kubectl apply -f portainer-agent.yaml + tail -f /dev/null + volumes: + - docker_data:/var/lib/docker + volumes: + docker_data: portainer_data: From aa5277de2e2c7b29c481d1b5d53850595fe0f7eb Mon Sep 17 00:00:00 2001 From: cong meng Date: Thu, 10 Dec 2020 13:58:10 +1300 Subject: [PATCH 007/157] fix(frontend): cannnot access configuration details view containing binary data (#4503) (#4561) Co-authored-by: Simon Meng --- app/kubernetes/services/configMapService.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/kubernetes/services/configMapService.js b/app/kubernetes/services/configMapService.js index 247af7497..be863eaeb 100644 --- a/app/kubernetes/services/configMapService.js +++ b/app/kubernetes/services/configMapService.js @@ -24,8 +24,11 @@ class KubernetesConfigMapService { try { const params = new KubernetesCommonParams(); params.id = name; - const [raw, yaml] = await Promise.all([this.KubernetesConfigMaps(namespace).get(params).$promise, this.KubernetesConfigMaps(namespace).getYaml(params).$promise]); - const configMap = KubernetesConfigMapConverter.apiToConfigMap(raw, yaml); + const [rawPromise, yamlPromise] = await Promise.allSettled([ + this.KubernetesConfigMaps(namespace).get(params).$promise, + this.KubernetesConfigMaps(namespace).getYaml(params).$promise, + ]); + const configMap = KubernetesConfigMapConverter.apiToConfigMap(rawPromise.value, yamlPromise.value); return configMap; } catch (err) { if (err.status === 404) { From 865c8d899b1bdec142b542bcbc8ae23bfdd2cdf5 Mon Sep 17 00:00:00 2001 From: cong meng Date: Thu, 10 Dec 2020 14:21:43 +1300 Subject: [PATCH 008/157] fix(frontend): revalidate configuration name when change resource pool (#4553) (#4562) Co-authored-by: Simon Meng --- .../configurations/create/createConfigurationController.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/kubernetes/views/configurations/create/createConfigurationController.js b/app/kubernetes/views/configurations/create/createConfigurationController.js index 7182c267d..31b76b918 100644 --- a/app/kubernetes/views/configurations/create/createConfigurationController.js +++ b/app/kubernetes/views/configurations/create/createConfigurationController.js @@ -25,6 +25,10 @@ class KubernetesCreateConfigurationController { this.state.alreadyExist = _.find(filteredConfigurations, (config) => config.Name === this.formValues.Name) !== undefined; } + onResourcePoolSelectionChange() { + this.onChangeName(); + } + isFormValid() { const uniqueCheck = !this.state.alreadyExist && this.state.isDataValid; if (this.formValues.IsSimple) { From 890bbf4058173b616a85b74e9c2ce744169a0004 Mon Sep 17 00:00:00 2001 From: Alice Groux Date: Thu, 10 Dec 2020 03:11:45 +0100 Subject: [PATCH 009/157] fix(k8s/sidebar): accessing cluster setup not expand endpoint sidebar (#4496) --- .../kubernetesSidebarContent.html | 2 +- app/portainer/views/sidebar/sidebar.html | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html b/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html index b83f8c2f9..90785a22c 100644 --- a/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html +++ b/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html @@ -16,6 +16,6 @@ diff --git a/app/portainer/views/sidebar/sidebar.html b/app/portainer/views/sidebar/sidebar.html index 578e4dd58..ca89daa22 100644 --- a/app/portainer/views/sidebar/sidebar.html +++ b/app/portainer/views/sidebar/sidebar.html @@ -127,7 +127,11 @@
Manage access + + Browse
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ Name + + Description +
Endpoint administratorFull control of all resources in an endpoint
HelpdeskRead-only access of all resources in an endpoint
Read-only userRead-only access of assigned resources in an endpoint
Standard userFull control of assigned resources in an endpoint
+ + + + + diff --git a/app/portainer/components/datatables/roles-datatable/rolesDatatable.js b/app/portainer/components/datatables/roles-datatable/rolesDatatable.js new file mode 100644 index 000000000..3cb7cf24a --- /dev/null +++ b/app/portainer/components/datatables/roles-datatable/rolesDatatable.js @@ -0,0 +1,12 @@ +angular.module('portainer.app').component('rolesDatatable', { + templateUrl: './rolesDatatable.html', + controller: 'GenericDatatableController', + bindings: { + titleText: '@', + titleIcon: '@', + dataset: '<', + tableKey: '@', + orderBy: '@', + reverseOrder: '<', + }, +}); diff --git a/app/portainer/views/roles/roles.html b/app/portainer/views/roles/roles.html new file mode 100644 index 000000000..a595909f1 --- /dev/null +++ b/app/portainer/views/roles/roles.html @@ -0,0 +1,56 @@ + + + + + + + Role management + + + + +

+ + This feature is available in Portainer Business Edition. +

+
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+ User +
+
+
+ + No user available + +
+
+ +
+ Access +
+
+
+ + Effective role for each endpoint will be displayed for the selected user +
+
+ +
+
+
+
+
diff --git a/app/portainer/views/settings/authentication/settingsAuthentication.html b/app/portainer/views/settings/authentication/settingsAuthentication.html index 0ecab33e1..9ceca1874 100644 --- a/app/portainer/views/settings/authentication/settingsAuthentication.html +++ b/app/portainer/views/settings/authentication/settingsAuthentication.html @@ -366,6 +366,57 @@ +
+
+ Provider +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ diff --git a/app/portainer/views/sidebar/sidebar.html b/app/portainer/views/sidebar/sidebar.html index ca89daa22..d1d181d92 100644 --- a/app/portainer/views/sidebar/sidebar.html +++ b/app/portainer/views/sidebar/sidebar.html @@ -120,11 +120,25 @@ ($state.current.name === 'portainer.users' || $state.current.name === 'portainer.users.user' || $state.current.name === 'portainer.teams' || - $state.current.name === 'portainer.teams.team') + $state.current.name === 'portainer.teams.team' || + $state.current.name === 'portainer.roles') " > Teams +