Compare commits
7 Commits
fix/EE-170
...
fix/EE-170
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0b58f57e5 | ||
|
|
689c2193c0 | ||
|
|
9121e8e69c | ||
|
|
53a2205f06 | ||
|
|
a098e24cca | ||
|
|
5d8c23e3a6 | ||
|
|
52f9320952 |
@@ -104,7 +104,7 @@ angular.module('portainer.docker').controller('ImageController', [
|
||||
try {
|
||||
const registryModel = await RegistryService.retrievePorRegistryModelFromRepository(repository, endpoint.Id);
|
||||
await ImageService.pullImage(registryModel);
|
||||
Notifications.success('Image successfully pushed', repository);
|
||||
Notifications.success('Image successfully pulled', repository);
|
||||
} catch (err) {
|
||||
Notifications.error('Failure', err, 'Unable to push image to repository');
|
||||
} finally {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<span class="small text-muted">
|
||||
<p>
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
This is a first version for Helm charts, for more information see this <a href="#">blog post.</a>
|
||||
This is a first version for Helm charts, for more information see this <a href="https://www.portainer.io/blog/portainer-now-with-helm-support" target="_blank">blog post</a>.
|
||||
</p>
|
||||
</span>
|
||||
</information-panel>
|
||||
|
||||
@@ -56,6 +56,7 @@ class KubernetesApplicationConverter {
|
||||
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.Metadata = data.metadata;
|
||||
|
||||
if (data.metadata.labels) {
|
||||
const { labels } = data.metadata;
|
||||
|
||||
@@ -449,8 +449,8 @@ class KubernetesApplicationHelper {
|
||||
// filter out all the applications that are managed by helm
|
||||
// to identify the helm managed applications, we need to check if the applications pod labels include
|
||||
// `app.kubernetes.io/instance` and `app.kubernetes.io/managed-by` = `helm`
|
||||
const helmManagedApps = applications.filter((app) =>
|
||||
app.Pods.flatMap((pod) => pod.Labels).some((label) => label && label[PodKubernetesInstanceLabel] && label[PodManagedByLabel] === 'Helm')
|
||||
const helmManagedApps = applications.filter(
|
||||
(app) => app.Metadata.labels && app.Metadata.labels[PodKubernetesInstanceLabel] && app.Metadata.labels[PodManagedByLabel] === 'Helm'
|
||||
);
|
||||
|
||||
// groups the helm managed applications by helm release name
|
||||
@@ -467,15 +467,12 @@ class KubernetesApplicationHelper {
|
||||
const namespacedHelmReleases = {};
|
||||
helmManagedApps.forEach((app) => {
|
||||
const namespace = app.ResourcePool;
|
||||
const labels = app.Pods.filter((p) => p.Labels).map((p) => p.Labels[PodKubernetesInstanceLabel]);
|
||||
const uniqueLabels = [...new Set(labels)];
|
||||
uniqueLabels.forEach((instanceStr) => {
|
||||
if (namespacedHelmReleases[namespace]) {
|
||||
namespacedHelmReleases[namespace][instanceStr] = [...(namespacedHelmReleases[namespace][instanceStr] || []), app];
|
||||
} else {
|
||||
namespacedHelmReleases[namespace] = { [instanceStr]: [app] };
|
||||
}
|
||||
});
|
||||
const instanceLabel = app.Metadata.labels[PodKubernetesInstanceLabel];
|
||||
if (namespacedHelmReleases[namespace]) {
|
||||
namespacedHelmReleases[namespace][instanceLabel] = [...(namespacedHelmReleases[namespace][instanceLabel] || []), app];
|
||||
} else {
|
||||
namespacedHelmReleases[namespace] = { [instanceLabel]: [app] };
|
||||
}
|
||||
});
|
||||
|
||||
// `helmAppsEntriesList` object structure:
|
||||
@@ -511,5 +508,25 @@ class KubernetesApplicationHelper {
|
||||
|
||||
return helmAppsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nested applications -
|
||||
* @param {KubernetesApplication[]} applications Application list
|
||||
* @returns {Object} { helmApplications: [app1, app2, ...], nonHelmApplications: [app3, app4, ...] }
|
||||
*/
|
||||
static getNestedApplications(applications) {
|
||||
const helmApplications = KubernetesApplicationHelper.getHelmApplications(applications);
|
||||
|
||||
// filter out helm managed applications
|
||||
const helmAppNames = [...new Set(helmApplications.map((hma) => hma.Name))]; // distinct helm app names
|
||||
const nonHelmApplications = applications.filter((app) => {
|
||||
if (app.Metadata.labels) {
|
||||
return !helmAppNames.includes(app.Metadata.labels[PodKubernetesInstanceLabel]);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return { helmApplications, nonHelmApplications };
|
||||
}
|
||||
}
|
||||
export default KubernetesApplicationHelper;
|
||||
|
||||
@@ -16,6 +16,7 @@ const _KubernetesApplication = Object.freeze({
|
||||
CreationDate: 0,
|
||||
Pods: [],
|
||||
Containers: [],
|
||||
Metadata: {},
|
||||
Limits: {},
|
||||
ServiceType: '',
|
||||
ServiceId: '',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
import KubernetesStackHelper from 'Kubernetes/helpers/stackHelper';
|
||||
import KubernetesApplicationHelper, { PodKubernetesInstanceLabel } from 'Kubernetes/helpers/application';
|
||||
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
|
||||
import KubernetesConfigurationHelper from 'Kubernetes/helpers/configurationHelper';
|
||||
import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
|
||||
|
||||
@@ -109,18 +109,9 @@ class KubernetesApplicationsController {
|
||||
try {
|
||||
const [applications, configurations] = await Promise.all([this.KubernetesApplicationService.get(), this.KubernetesConfigurationService.get()]);
|
||||
const configuredApplications = KubernetesConfigurationHelper.getApplicationConfigurations(applications, configurations);
|
||||
const helmApplications = KubernetesApplicationHelper.getHelmApplications(configuredApplications);
|
||||
const { helmApplications, nonHelmApplications } = KubernetesApplicationHelper.getNestedApplications(configuredApplications);
|
||||
|
||||
// filter out multi-chart helm managed applications
|
||||
const helmAppNames = [...new Set(helmApplications.map((hma) => hma.Name))]; // distinct helm app names
|
||||
const nonHelmApps = configuredApplications.filter(
|
||||
(app) =>
|
||||
!app.Pods.flatMap((pod) => pod.Labels) // flatten pod labels
|
||||
.filter((label) => label) // filter out empty labels
|
||||
.some((label) => helmAppNames.includes(label[PodKubernetesInstanceLabel])) // check if label key is in helmAppNames
|
||||
);
|
||||
|
||||
this.state.applications = [...nonHelmApps, ...helmApplications];
|
||||
this.state.applications = [...helmApplications, ...nonHelmApplications];
|
||||
this.state.stacks = KubernetesStackHelper.stacksFromApplications(applications);
|
||||
this.state.ports = KubernetesApplicationHelper.portMappingsFromApplications(applications);
|
||||
} catch (err) {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
>
|
||||
<template-item-actions>
|
||||
<div ng-if="$ctrl.isEditAllowed(template)" style="display: flex;">
|
||||
<a ui-state="$ctrl.editPath" ui-state-params="({id: template.Id})" ng-click="$event.stopPropagation();" class="btn btn-primary btn-xs" style="margin-right: 10px;">
|
||||
<a ui-state="$ctrl.editPath" ui-state-params="{id: template.Id}" ng-click="$event.stopPropagation();" class="btn btn-primary btn-xs" style="margin-right: 10px;">
|
||||
Edit
|
||||
</a>
|
||||
<button class="btn btn-danger btn-xs" ng-click="$ctrl.onDeleteClick(template.Id); $event.stopPropagation();">Delete</button>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
templates="$ctrl.templates"
|
||||
table-key="customTemplates"
|
||||
create-path="docker.templates.custom.new"
|
||||
edit-path="docker.templates.custom.edit"
|
||||
is-edit-allowed="$ctrl.isEditAllowed"
|
||||
on-select-click="($ctrl.selectTemplate)"
|
||||
on-delete-click="($ctrl.confirmDelete)"
|
||||
|
||||
@@ -283,7 +283,7 @@ docker run -d \\
|
||||
-e CAP_HOST_MANAGEMENT=1 \\
|
||||
-e EDGE_INSECURE_POLL=${allowSelfSignedCerts ? 1 : 0} \\
|
||||
--name portainer_edge_agent \\
|
||||
portainer/agent:2.4.0`;
|
||||
portainer/agent`;
|
||||
}
|
||||
|
||||
function buildWindowsStandaloneCommand(edgeId, edgeKey, allowSelfSignedCerts) {
|
||||
|
||||
@@ -34,7 +34,7 @@ angular
|
||||
StackFile: null,
|
||||
RepositoryURL: '',
|
||||
RepositoryReferenceName: '',
|
||||
RepositoryAuthentication: true,
|
||||
RepositoryAuthentication: false,
|
||||
RepositoryUsername: '',
|
||||
RepositoryPassword: '',
|
||||
Env: [],
|
||||
|
||||
@@ -70,7 +70,7 @@ module.exports = {
|
||||
compress: true,
|
||||
port: 8999,
|
||||
proxy: {
|
||||
'/api': 'https://localhost:9443',
|
||||
'/api': 'http://localhost:9000',
|
||||
},
|
||||
open: true,
|
||||
writeToDisk: true,
|
||||
|
||||
Reference in New Issue
Block a user