mirror of
https://github.com/portainer/portainer.git
synced 2025-08-04 21:35:23 +02:00
Merge branch 'develop' into feat/EE-809/EE-466/kube-advanced-apps
This commit is contained in:
commit
0979e6ec8f
97 changed files with 1155 additions and 314 deletions
|
@ -8,7 +8,7 @@
|
|||
<div ng-include="'app/kubernetes/templates/advancedDeploymentPanel.html'"></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-12" data-cy="k8sApp-appList">
|
||||
<rd-widget>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<uib-tabset active="ctrl.state.activeTab" justified="true" type="pills">
|
||||
|
|
|
@ -1602,6 +1602,7 @@
|
|||
ng-disabled="!kubernetesApplicationCreationForm.$valid || ctrl.isDeployUpdateButtonDisabled() || !ctrl.state.pullImageValidity"
|
||||
ng-click="ctrl.deployApplication()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
data-cy="k8sAppCreate-deployButton"
|
||||
>
|
||||
<span ng-show="!ctrl.state.isEdit && !ctrl.state.actionInProgress">Deploy application</span>
|
||||
<span ng-show="!ctrl.state.isEdit && ctrl.state.actionInProgress">Deployment in progress...</span>
|
||||
|
|
|
@ -29,6 +29,7 @@ import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceRese
|
|||
import { KubernetesServiceTypes } from 'Kubernetes/models/service/models';
|
||||
import KubernetesApplicationHelper from 'Kubernetes/helpers/application/index';
|
||||
import KubernetesVolumeHelper from 'Kubernetes/helpers/volumeHelper';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
import { KubernetesNodeHelper } from 'Kubernetes/node/helper';
|
||||
|
||||
class KubernetesCreateApplicationController {
|
||||
|
@ -48,7 +49,6 @@ class KubernetesCreateApplicationController {
|
|||
KubernetesNodeService,
|
||||
KubernetesIngressService,
|
||||
KubernetesPersistentVolumeClaimService,
|
||||
KubernetesNamespaceHelper,
|
||||
KubernetesVolumeService,
|
||||
RegistryService,
|
||||
StackService
|
||||
|
@ -66,7 +66,6 @@ class KubernetesCreateApplicationController {
|
|||
this.KubernetesVolumeService = KubernetesVolumeService;
|
||||
this.KubernetesIngressService = KubernetesIngressService;
|
||||
this.KubernetesPersistentVolumeClaimService = KubernetesPersistentVolumeClaimService;
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
this.RegistryService = RegistryService;
|
||||
this.StackService = StackService;
|
||||
|
||||
|
@ -996,7 +995,7 @@ class KubernetesCreateApplicationController {
|
|||
]);
|
||||
this.ingresses = ingresses;
|
||||
|
||||
this.resourcePools = _.filter(resourcePools, (resourcePool) => !this.KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name));
|
||||
this.resourcePools = _.filter(resourcePools, (resourcePool) => !KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name));
|
||||
this.formValues.ResourcePool = this.resourcePools[0];
|
||||
if (!this.formValues.ResourcePool) {
|
||||
return;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>
|
||||
<td data-cy="k8sAppDetail-appName">
|
||||
{{ ctrl.application.Name }}
|
||||
<span class="label label-primary image-tag label-margins" ng-if="!ctrl.isSystemNamespace() && ctrl.isExternalApplication()">external</span>
|
||||
</td>
|
||||
|
@ -30,9 +30,9 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Namespace</td>
|
||||
<td>
|
||||
<td data-cy="k8sAppDetail-resourcePoolName">
|
||||
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: ctrl.application.ResourcePool })">{{ ctrl.application.ResourcePool }}</a>
|
||||
<span style="margin-left: 5px;" class="label label-info image-tag" ng-if="ctrl.isSystemNamespace(item)">system</span>
|
||||
<span style="margin-left: 5px;" class="label label-info image-tag" ng-if="ctrl.isSystemNamespace()">system</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -46,7 +46,8 @@
|
|||
<td ng-if="ctrl.application.ApplicationType !== ctrl.KubernetesApplicationTypes.POD">
|
||||
<span ng-if="ctrl.application.DeploymentType === ctrl.KubernetesApplicationDeploymentTypes.REPLICATED">Replicated</span>
|
||||
<span ng-if="ctrl.application.DeploymentType === ctrl.KubernetesApplicationDeploymentTypes.GLOBAL">Global</span>
|
||||
<code>{{ ctrl.application.RunningPodsCount }}</code> / <code>{{ ctrl.application.TotalPodsCount }}</code>
|
||||
<code data-cy="k8sAppDetail-runningPods">{{ ctrl.application.RunningPodsCount }}</code> /
|
||||
<code data-cy="k8sAppDetail-totalPods">{{ ctrl.application.TotalPodsCount }}</code>
|
||||
</td>
|
||||
<td ng-if="ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD">
|
||||
{{ ctrl.application.Pods[0].Status }}
|
||||
|
@ -318,9 +319,9 @@
|
|||
<td style="width: 50%;">HTTP route</td>
|
||||
</tr>
|
||||
<tr ng-repeat-start="port in ctrl.application.PublishedPorts">
|
||||
<td ng-if="!ctrl.portHasIngressRules(port)">{{ port.TargetPort }}/{{ port.Protocol }}</td>
|
||||
<td ng-if="!ctrl.portHasIngressRules(port)" data-cy="k8sAppDetail-containerPort">{{ port.TargetPort }}/{{ port.Protocol }}</td>
|
||||
<td ng-if="!ctrl.portHasIngressRules(port)">
|
||||
<span ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.NODE_PORT">
|
||||
<span ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.NODE_PORT" data-cy="k8sAppDetail-nodePort">
|
||||
{{ port.NodePort }}
|
||||
</span>
|
||||
<span ng-if="ctrl.application.ServiceType !== ctrl.KubernetesServiceTypes.NODE_PORT">
|
||||
|
|
|
@ -12,6 +12,7 @@ import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
|
|||
import { KubernetesServiceTypes } from 'Kubernetes/models/service/models';
|
||||
import { KubernetesPodNodeAffinityNodeSelectorRequirementOperators } from 'Kubernetes/pod/models';
|
||||
import { KubernetesPodContainerTypes } from 'Kubernetes/pod/models/index';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
function computeTolerations(nodes, application) {
|
||||
const pod = application.Pods[0];
|
||||
|
@ -111,7 +112,6 @@ class KubernetesApplicationController {
|
|||
KubernetesStackService,
|
||||
KubernetesPodService,
|
||||
KubernetesNodeService,
|
||||
KubernetesNamespaceHelper,
|
||||
EndpointProvider
|
||||
) {
|
||||
this.$async = $async;
|
||||
|
@ -127,8 +127,6 @@ class KubernetesApplicationController {
|
|||
this.KubernetesPodService = KubernetesPodService;
|
||||
this.KubernetesNodeService = KubernetesNodeService;
|
||||
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
|
||||
this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes;
|
||||
this.KubernetesApplicationTypes = KubernetesApplicationTypes;
|
||||
this.EndpointProvider = EndpointProvider;
|
||||
|
@ -160,7 +158,7 @@ class KubernetesApplicationController {
|
|||
}
|
||||
|
||||
isSystemNamespace() {
|
||||
return this.KubernetesNamespaceHelper.isSystemNamespace(this.application.ResourcePool);
|
||||
return KubernetesNamespaceHelper.isSystemNamespace(this.application.ResourcePool);
|
||||
}
|
||||
|
||||
isExternalApplication() {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
placeholder="my-configuration"
|
||||
auto-focus
|
||||
required
|
||||
data-cy="k8sConfigCreate-nameInput"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,6 +57,7 @@
|
|||
id="resource-pool-selector"
|
||||
ng-model="ctrl.formValues.ResourcePool"
|
||||
ng-options="resourcePool.Namespace.Name for resourcePool in ctrl.resourcePools"
|
||||
data-cy="k8sConfigCreate-namespaceDropdown"
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,7 +85,7 @@
|
|||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="type_basic" ng-value="ctrl.KubernetesConfigurationTypes.CONFIGMAP" ng-model="ctrl.formValues.Type" />
|
||||
<label for="type_basic">
|
||||
<label for="type_basic" data-cy="k8sConfigCreate-nonSensitiveButton">
|
||||
<div class="boxselector_header">
|
||||
<i class="fa fa-file-code" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Non-sensitive
|
||||
|
@ -93,7 +95,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<input type="radio" id="type_secret" ng-value="ctrl.KubernetesConfigurationTypes.SECRET" ng-model="ctrl.formValues.Type" />
|
||||
<label for="type_secret">
|
||||
<label for="type_secret" data-cy="k8sConfigCreate-sensitiveButton">
|
||||
<div class="boxselector_header">
|
||||
<i class="fa fa-user-secret" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Sensitive
|
||||
|
@ -141,6 +143,7 @@
|
|||
ng-disabled="!kubernetesConfigurationCreationForm.$valid || !ctrl.isFormValid() || ctrl.state.actionInProgress"
|
||||
ng-click="ctrl.createConfiguration()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
data-cy="k8sConfigCreate-CreateConfigButton"
|
||||
>
|
||||
<span ng-hide="ctrl.state.actionInProgress">Create configuration</span>
|
||||
<span ng-show="ctrl.state.actionInProgress">Creation in progress...</span>
|
||||
|
|
|
@ -3,10 +3,11 @@ import _ from 'lodash-es';
|
|||
import { KubernetesConfigurationFormValues, KubernetesConfigurationFormValuesEntry } from 'Kubernetes/models/configuration/formvalues';
|
||||
import { KubernetesConfigurationTypes } from 'Kubernetes/models/configuration/models';
|
||||
import KubernetesConfigurationHelper from 'Kubernetes/helpers/configurationHelper';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
class KubernetesCreateConfigurationController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $window, ModalService, Notifications, Authentication, KubernetesConfigurationService, KubernetesResourcePoolService, KubernetesNamespaceHelper) {
|
||||
constructor($async, $state, $window, ModalService, Notifications, Authentication, KubernetesConfigurationService, KubernetesResourcePoolService) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$window = $window;
|
||||
|
@ -16,7 +17,6 @@ class KubernetesCreateConfigurationController {
|
|||
this.KubernetesConfigurationService = KubernetesConfigurationService;
|
||||
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
|
||||
this.KubernetesConfigurationTypes = KubernetesConfigurationTypes;
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
|
||||
this.onInit = this.onInit.bind(this);
|
||||
this.createConfigurationAsync = this.createConfigurationAsync.bind(this);
|
||||
|
@ -94,7 +94,7 @@ class KubernetesCreateConfigurationController {
|
|||
|
||||
try {
|
||||
const resourcePools = await this.KubernetesResourcePoolService.get();
|
||||
this.resourcePools = _.filter(resourcePools, (resourcePool) => !this.KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name));
|
||||
this.resourcePools = _.filter(resourcePools, (resourcePool) => !KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name));
|
||||
|
||||
this.formValues.ResourcePool = this.resourcePools[0];
|
||||
await this.getConfigurations();
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
<rd-widget>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<uib-tabset active="ctrl.state.activeTab" justified="true" type="pills">
|
||||
<uib-tab index="0" classes="btn-sm" select="ctrl.selectTab(0)">
|
||||
<uib-tab index="0" classes="btn-sm" select="ctrl.selectTab(0)" data-cy="k8sConfigDetail-configTab">
|
||||
<uib-tab-heading> <i class="fa fa-file-code space-right" aria-hidden="true"></i> Configuration </uib-tab-heading>
|
||||
<div style="padding: 20px;">
|
||||
<table class="table">
|
||||
<table class="table" data-cy="k8sConfigDetail-configTable">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
|
@ -41,7 +41,7 @@
|
|||
</table>
|
||||
</div>
|
||||
</uib-tab>
|
||||
<uib-tab index="1" classes="btn-sm" select="ctrl.selectTab(1)">
|
||||
<uib-tab index="1" classes="btn-sm" select="ctrl.selectTab(1)" data-cy="k8sConfigDetail-eventsTab">
|
||||
<uib-tab-heading>
|
||||
<i class="fa fa-history space-right" aria-hidden="true"></i> Events
|
||||
<div ng-if="ctrl.hasEventWarnings()">
|
||||
|
@ -61,7 +61,7 @@
|
|||
>
|
||||
</kubernetes-events-datatable>
|
||||
</uib-tab>
|
||||
<uib-tab index="2" ng-if="ctrl.configuration.Yaml" classes="btn-sm" select="ctrl.showEditor()">
|
||||
<uib-tab index="2" ng-if="ctrl.configuration.Yaml" classes="btn-sm" select="ctrl.showEditor()" data-cy="k8sConfigDetail-yamlTab">
|
||||
<uib-tab-heading> <i class="fa fa-code space-right" aria-hidden="true"></i> YAML </uib-tab-heading>
|
||||
<div style="padding-right: 25px;" ng-if="ctrl.state.showEditorTab">
|
||||
<kubernetes-yaml-inspector key="configuration-yaml" data="ctrl.configuration.Yaml"> </kubernetes-yaml-inspector>
|
||||
|
@ -104,6 +104,7 @@
|
|||
ng-disabled="!ctrl.isFormValid() || !kubernetesConfigurationCreationForm.$valid || ctrl.state.actionInProgress"
|
||||
ng-click="ctrl.updateConfiguration()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
data-cy="k8sConfigDetail-updateConfig"
|
||||
>
|
||||
<span ng-hide="ctrl.state.actionInProgress">Update configuration</span>
|
||||
<span ng-show="ctrl.state.actionInProgress">Update in progress...</span>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
|
||||
import { KubernetesConfigurationFormValues } from 'Kubernetes/models/configuration/formvalues';
|
||||
import { KubernetesConfigurationTypes } from 'Kubernetes/models/configuration/models';
|
||||
import KubernetesConfigurationHelper from 'Kubernetes/helpers/configurationHelper';
|
||||
import KubernetesConfigurationConverter from 'Kubernetes/converters/configuration';
|
||||
import KubernetesEventHelper from 'Kubernetes/helpers/eventHelper';
|
||||
import _ from 'lodash-es';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
class KubernetesConfigurationController {
|
||||
/* @ngInject */
|
||||
|
@ -21,8 +23,7 @@ class KubernetesConfigurationController {
|
|||
KubernetesResourcePoolService,
|
||||
ModalService,
|
||||
KubernetesApplicationService,
|
||||
KubernetesEventService,
|
||||
KubernetesNamespaceHelper
|
||||
KubernetesEventService
|
||||
) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
|
@ -36,7 +37,6 @@ class KubernetesConfigurationController {
|
|||
this.KubernetesApplicationService = KubernetesApplicationService;
|
||||
this.KubernetesEventService = KubernetesEventService;
|
||||
this.KubernetesConfigurationTypes = KubernetesConfigurationTypes;
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
this.KubernetesConfigMapService = KubernetesConfigMapService;
|
||||
this.KubernetesSecretService = KubernetesSecretService;
|
||||
|
||||
|
@ -52,7 +52,7 @@ class KubernetesConfigurationController {
|
|||
}
|
||||
|
||||
isSystemNamespace() {
|
||||
return this.KubernetesNamespaceHelper.isSystemNamespace(this.configuration.Namespace);
|
||||
return KubernetesNamespaceHelper.isSystemNamespace(this.configuration.Namespace);
|
||||
}
|
||||
|
||||
isSystemConfig() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { KubernetesFormValidationReferences } from 'Kubernetes/models/applicatio
|
|||
import { KubernetesIngressClass } from 'Kubernetes/ingress/models';
|
||||
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
|
||||
import { KubernetesIngressClassTypes } from 'Kubernetes/ingress/constants';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
class KubernetesConfigureController {
|
||||
/* #region CONSTRUCTOR */
|
||||
|
@ -18,7 +19,6 @@ class KubernetesConfigureController {
|
|||
EndpointService,
|
||||
EndpointProvider,
|
||||
ModalService,
|
||||
KubernetesNamespaceHelper,
|
||||
KubernetesResourcePoolService,
|
||||
KubernetesIngressService,
|
||||
KubernetesMetricsService
|
||||
|
@ -30,7 +30,6 @@ class KubernetesConfigureController {
|
|||
this.EndpointService = EndpointService;
|
||||
this.EndpointProvider = EndpointProvider;
|
||||
this.ModalService = ModalService;
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
|
||||
this.KubernetesIngressService = KubernetesIngressService;
|
||||
this.KubernetesMetricsService = KubernetesMetricsService;
|
||||
|
@ -147,8 +146,7 @@ class KubernetesConfigureController {
|
|||
const allResourcePools = await this.KubernetesResourcePoolService.get();
|
||||
const resourcePools = _.filter(
|
||||
allResourcePools,
|
||||
(resourcePool) =>
|
||||
!this.KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name) && !this.KubernetesNamespaceHelper.isDefaultNamespace(resourcePool.Namespace.Name)
|
||||
(resourcePool) => !KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name) && !KubernetesNamespaceHelper.isDefaultNamespace(resourcePool.Namespace.Name)
|
||||
);
|
||||
|
||||
ingressesToDel.forEach((ingress) => {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.pools">
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.pools" data-cy="k8sDashboard-namespaces">
|
||||
<a ui-sref="kubernetes.resourcePools">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
|
@ -47,7 +47,7 @@
|
|||
</rd-widget>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.applications">
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.applications" data-cy="k8sDashboard-applications">
|
||||
<a ui-sref="kubernetes.applications">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
|
@ -60,7 +60,7 @@
|
|||
</rd-widget>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.configurations">
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.configurations" data-cy="k8sDashboard-configurations">
|
||||
<a ui-sref="kubernetes.configurations">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
|
@ -73,7 +73,7 @@
|
|||
</rd-widget>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.volumes">
|
||||
<div class="col-xs-12 col-md-6" ng-if="ctrl.volumes" data-cy="k8sDashboard-volumes">
|
||||
<a ui-sref="kubernetes.volumes">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
import KubernetesConfigurationHelper from 'Kubernetes/helpers/configurationHelper';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
class KubernetesDashboardController {
|
||||
/* @ngInject */
|
||||
|
@ -13,7 +14,6 @@ class KubernetesDashboardController {
|
|||
KubernetesApplicationService,
|
||||
KubernetesConfigurationService,
|
||||
KubernetesVolumeService,
|
||||
KubernetesNamespaceHelper,
|
||||
Authentication,
|
||||
TagService
|
||||
) {
|
||||
|
@ -25,7 +25,6 @@ class KubernetesDashboardController {
|
|||
this.KubernetesApplicationService = KubernetesApplicationService;
|
||||
this.KubernetesConfigurationService = KubernetesConfigurationService;
|
||||
this.KubernetesVolumeService = KubernetesVolumeService;
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
this.Authentication = Authentication;
|
||||
this.TagService = TagService;
|
||||
|
||||
|
@ -65,13 +64,8 @@ class KubernetesDashboardController {
|
|||
: '-';
|
||||
|
||||
if (!isAdmin) {
|
||||
this.pools = _.filter(pools, (pool) => {
|
||||
return !this.KubernetesNamespaceHelper.isSystemNamespace(pool.Namespace.Name);
|
||||
});
|
||||
|
||||
this.configurations = _.filter(configurations, (config) => {
|
||||
return !KubernetesConfigurationHelper.isSystemToken(config);
|
||||
});
|
||||
this.pools = _.filter(pools, (pool) => !KubernetesNamespaceHelper.isSystemNamespace(pool.Namespace.Name));
|
||||
this.configurations = _.filter(configurations, (config) => !KubernetesConfigurationHelper.isSystemToken(config));
|
||||
} else {
|
||||
this.pools = pools;
|
||||
this.configurations = configurations;
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
<div class="col-sm-12 form-section-title">
|
||||
Deployment type
|
||||
</div>
|
||||
<box-selector radio-name="deploy" ng-model="ctrl.state.DeployType" options="ctrl.deployOptions"></box-selector>
|
||||
<box-selector radio-name="deploy" ng-model="ctrl.state.DeployType" options="ctrl.deployOptions" data-cy="k8sAppDeploy-deploymentSelector"></box-selector>
|
||||
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Build method
|
||||
</div>
|
||||
<box-selector radio-name="method" ng-model="ctrl.state.BuildMethod" options="ctrl.methodOptions"></box-selector>
|
||||
<box-selector radio-name="method" ng-model="ctrl.state.BuildMethod" options="ctrl.methodOptions" data-cy="k8sAppDeploy-buildSelector"></box-selector>
|
||||
|
||||
<!-- repository -->
|
||||
<div ng-show="ctrl.state.BuildMethod === ctrl.BuildMethods.GIT">
|
||||
|
@ -48,7 +48,14 @@
|
|||
<div class="form-group">
|
||||
<label for="stack_repository_path" class="col-sm-2 control-label text-left">Manifest path</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="ctrl.formValues.FilePathInRepository" id="stack_manifest_path" placeholder="deployment.yml" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="ctrl.formValues.FilePathInRepository"
|
||||
id="stack_manifest_path"
|
||||
placeholder="deployment.yml"
|
||||
data-cy="k8sAppDeploy-gitManifestPath"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<git-form-auth-fieldset model="ctrl.formValues" on-change="(ctrl.onChangeFormValues)"></git-form-auth-fieldset>
|
||||
|
@ -100,7 +107,14 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-disabled="ctrl.disableDeploy()" ng-click="ctrl.deploy()" button-spinner="ctrl.state.actionInProgress">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="ctrl.disableDeploy()"
|
||||
ng-click="ctrl.deploy()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
data-cy="k8sAppDeploy-deployButton"
|
||||
>
|
||||
<span ng-hide="ctrl.state.actionInProgress">Deploy</span>
|
||||
<span ng-show="ctrl.state.actionInProgress">Deployment in progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
ng-pattern="/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/"
|
||||
ng-change="$ctrl.onChangeName()"
|
||||
placeholder="my-project"
|
||||
data-cy="k8sNamespaceCreate-namespaceNameInput"
|
||||
required
|
||||
auto-focus
|
||||
/>
|
||||
|
@ -58,7 +59,9 @@
|
|||
<label class="control-label text-left">
|
||||
Resource assignment
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="$ctrl.formValues.HasQuota" /><i></i> </label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" ng-model="$ctrl.formValues.HasQuota" /><i data-cy="k8sNamespaceCreate-resourceAssignmentToggle"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="$ctrl.formValues.HasQuota && !$ctrl.isQuotaValid()">
|
||||
|
@ -84,6 +87,7 @@
|
|||
ceil="$ctrl.state.sliderMaxMemory"
|
||||
step="128"
|
||||
ng-if="$ctrl.state.sliderMaxMemory"
|
||||
data-cy="k8sNamespaceCreate-memoryLimitSlider"
|
||||
>
|
||||
</slider>
|
||||
</div>
|
||||
|
@ -96,6 +100,7 @@
|
|||
class="form-control"
|
||||
ng-model="$ctrl.formValues.MemoryLimit"
|
||||
id="memory-limit"
|
||||
data-cy="k8sNamespaceCreate-memoryLimitInput"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
@ -128,6 +133,7 @@
|
|||
step="0.1"
|
||||
precision="2"
|
||||
ng-if="$ctrl.state.sliderMaxCpu"
|
||||
data-cy="k8sNamespaceCreate-cpuLimitSlider"
|
||||
>
|
||||
</slider>
|
||||
</div>
|
||||
|
@ -159,7 +165,7 @@
|
|||
<label class="control-label text-left">
|
||||
Load Balancer quota
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" disabled /><i></i> </label>
|
||||
<label class="switch" style="margin-left: 20px;" data-cy="k8sNamespaceCreate-loadBalancerQuotaToggle"> <input type="checkbox" disabled /><i></i> </label>
|
||||
<span class="text-muted small" style="margin-left: 15px;">
|
||||
<i class="fa fa-user" aria-hidden="true"></i>
|
||||
This feature is available in <a href="https://www.portainer.io/business-upsell?from=k8s-resourcepool-lbquota" target="_blank"> Portainer Business Edition</a>.
|
||||
|
@ -189,7 +195,7 @@
|
|||
<label class="control-label text-left">
|
||||
Enable quota
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" disabled /><i></i> </label>
|
||||
<label class="switch" style="margin-left: 20px;" data-cy="k8sNamespaceCreate-enableQuotaToggle"> <input type="checkbox" disabled /><i></i> </label>
|
||||
<span class="text-muted small" style="margin-left: 15px;">
|
||||
<i class="fa fa-user" aria-hidden="true"></i>
|
||||
This feature is available in
|
||||
|
@ -409,7 +415,7 @@
|
|||
ng-click="$ctrl.createResourcePool()"
|
||||
button-spinner="$ctrl.state.actionInProgress"
|
||||
>
|
||||
<span ng-hide="$ctrl.state.actionInProgress">Create namespace</span>
|
||||
<span ng-hide="$ctrl.state.actionInProgress" data-cy="k8sNamespace-createNamespaceButton">Create namespace</span>
|
||||
<span ng-show="$ctrl.state.actionInProgress">Creation in progress...</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -15,9 +15,18 @@
|
|||
<form class="form-horizontal" autocomplete="off" name="resourcePoolEditForm" style="padding: 20px; margin-top: 10px;">
|
||||
<!-- name-input -->
|
||||
<div class="form-group">
|
||||
<label for="pool_name" class="col-sm-1 control-label text-left">Name</label>
|
||||
<div class="col-sm-11">
|
||||
<input type="text" class="form-control" name="pool_name" ng-model="ctrl.pool.Namespace.Name" disabled />
|
||||
<div class="col-sm-12">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>
|
||||
{{ ctrl.pool.Namespace.Name }}
|
||||
<span class="label label-info image-tag label-margins" ng-if="ctrl.isSystem">system</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !name-input -->
|
||||
|
@ -396,21 +405,26 @@
|
|||
<!-- !summary -->
|
||||
|
||||
<!-- actions -->
|
||||
<div ng-if="ctrl.isAdmin && ctrl.isEditable" class="col-sm-12 form-section-title">
|
||||
<div ng-if="ctrl.isAdmin && !ctrl.isDefaultNamespace" class="col-sm-12 form-section-title">
|
||||
Actions
|
||||
</div>
|
||||
<div ng-if="ctrl.isAdmin && ctrl.isEditable" class="form-group">
|
||||
<div ng-if="ctrl.isAdmin && !ctrl.isDefaultNamespace" class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button
|
||||
type="button"
|
||||
ng-if="ctrl.isEditable"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="!resourcePoolEditForm.$valid || ctrl.isUpdateButtonDisabled()"
|
||||
ng-click="ctrl.updateResourcePool()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
>
|
||||
<span ng-hide="ctrl.state.actionInProgress">Update namespace</span>
|
||||
<span ng-hide="ctrl.state.actionInProgress" data-cy="k8sNamespaceEdit-updateNamespaceButton">Update namespace</span>
|
||||
<span ng-show="ctrl.state.actionInProgress">Update in progress...</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-click="ctrl.markUnmarkAsSystem()" button-spinner="ctrl.state.actionInProgress">
|
||||
<span ng-if="ctrl.isSystem">Unmark as system</span>
|
||||
<span ng-if="!ctrl.isSystem">Mark as system</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !actions -->
|
||||
|
|
|
@ -15,6 +15,7 @@ import { KubernetesFormValidationReferences } from 'Kubernetes/models/applicatio
|
|||
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
|
||||
import { KubernetesIngressClassTypes } from 'Kubernetes/ingress/constants';
|
||||
import KubernetesResourceQuotaConverter from 'Kubernetes/converters/resourceQuota';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
class KubernetesResourcePoolController {
|
||||
/* #region CONSTRUCTOR */
|
||||
|
@ -34,7 +35,6 @@ class KubernetesResourcePoolController {
|
|||
KubernetesEventService,
|
||||
KubernetesPodService,
|
||||
KubernetesApplicationService,
|
||||
KubernetesNamespaceHelper,
|
||||
KubernetesIngressService,
|
||||
KubernetesVolumeService
|
||||
) {
|
||||
|
@ -53,7 +53,6 @@ class KubernetesResourcePoolController {
|
|||
KubernetesEventService,
|
||||
KubernetesPodService,
|
||||
KubernetesApplicationService,
|
||||
KubernetesNamespaceHelper,
|
||||
KubernetesIngressService,
|
||||
KubernetesVolumeService,
|
||||
});
|
||||
|
@ -171,11 +170,11 @@ class KubernetesResourcePoolController {
|
|||
}
|
||||
|
||||
/* #region UPDATE NAMESPACE */
|
||||
async updateResourcePoolAsync() {
|
||||
async updateResourcePoolAsync(oldFormValues, newFormValues) {
|
||||
this.state.actionInProgress = true;
|
||||
try {
|
||||
this.checkDefaults();
|
||||
await this.KubernetesResourcePoolService.patch(this.savedFormValues, this.formValues);
|
||||
await this.KubernetesResourcePoolService.patch(oldFormValues, newFormValues);
|
||||
this.Notifications.success('Namespace successfully updated', this.pool.Namespace.Name);
|
||||
this.$state.reload();
|
||||
} catch (err) {
|
||||
|
@ -202,13 +201,45 @@ class KubernetesResourcePoolController {
|
|||
${warnings.ingress ? messages.ingress : ''}<br/><br/>Do you wish to continue?`;
|
||||
this.ModalService.confirmUpdate(displayedMessage, (confirmed) => {
|
||||
if (confirmed) {
|
||||
return this.$async(this.updateResourcePoolAsync);
|
||||
return this.$async(this.updateResourcePoolAsync, this.savedFormValues, this.formValues);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return this.$async(this.updateResourcePoolAsync);
|
||||
return this.$async(this.updateResourcePoolAsync, this.savedFormValues, this.formValues);
|
||||
}
|
||||
}
|
||||
|
||||
async confirmMarkUnmarkAsSystem() {
|
||||
const message = this.isSystem
|
||||
? 'Unmarking this namespace as system will allow non administrator users to manage it and the resources in contains depending on the access control settings. Are you sure?'
|
||||
: 'Marking this namespace as a system namespace will prevent non administrator users from managing it and the resources it contains. Are you sure?';
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.ModalService.confirmUpdate(message, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
markUnmarkAsSystem() {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
const namespaceName = this.$state.params.id;
|
||||
this.state.actionInProgress = true;
|
||||
|
||||
const confirmed = await this.confirmMarkUnmarkAsSystem();
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
await this.KubernetesResourcePoolService.toggleSystem(this.endpoint.Id, namespaceName, !this.isSystem);
|
||||
|
||||
this.Notifications.success('Namespace successfully updated', namespaceName);
|
||||
this.$state.reload();
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to create namespace');
|
||||
} finally {
|
||||
this.state.actionInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
hasEventWarnings() {
|
||||
|
@ -361,6 +392,7 @@ class KubernetesResourcePoolController {
|
|||
this.formValues = new KubernetesResourcePoolFormValues(KubernetesResourceQuotaDefaults);
|
||||
this.formValues.Name = this.pool.Namespace.Name;
|
||||
this.formValues.EndpointId = this.endpoint.Id;
|
||||
this.formValues.IsSystem = this.pool.Namespace.IsSystem;
|
||||
|
||||
_.forEach(nodes, (item) => {
|
||||
this.state.sliderMaxMemory += filesizeParser(item.Memory);
|
||||
|
@ -377,11 +409,9 @@ class KubernetesResourcePoolController {
|
|||
this.state.resourceReservation.CPU = quota.CpuLimitUsed;
|
||||
this.state.resourceReservation.Memory = KubernetesResourceReservationHelper.megaBytesValue(quota.MemoryLimitUsed);
|
||||
}
|
||||
|
||||
this.isEditable = !this.KubernetesNamespaceHelper.isSystemNamespace(this.pool.Namespace.Name);
|
||||
if (this.pool.Namespace.Name === 'default') {
|
||||
this.isEditable = false;
|
||||
}
|
||||
this.isSystem = KubernetesNamespaceHelper.isSystemNamespace(this.pool.Namespace.Name);
|
||||
this.isDefaultNamespace = KubernetesNamespaceHelper.isDefaultNamespace(this.pool.Namespace.Name);
|
||||
this.isEditable = !this.isSystem && !this.isDefaultNamespace;
|
||||
|
||||
await this.getEvents();
|
||||
await this.getApplications();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
remove-action="ctrl.removeAction"
|
||||
refresh-callback="ctrl.getResourcePools"
|
||||
endpoint="ctrl.endpoint"
|
||||
data-cy="k8sNamespace-namespaceTable"
|
||||
></kubernetes-resource-pools-datatable>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<td>Namespace</td>
|
||||
<td>
|
||||
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: ctrl.volume.ResourcePool.Namespace.Name })">{{ ctrl.volume.ResourcePool.Namespace.Name }}</a>
|
||||
<span style="margin-left: 5px;" class="label label-info image-tag" ng-if="ctrl.isSystemNamespace(item)">system</span>
|
||||
<span style="margin-left: 5px;" class="label label-info image-tag" ng-if="ctrl.isSystemNamespace()">system</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -4,6 +4,7 @@ import KubernetesVolumeHelper from 'Kubernetes/helpers/volumeHelper';
|
|||
import KubernetesEventHelper from 'Kubernetes/helpers/eventHelper';
|
||||
import { KubernetesStorageClassAccessPolicies } from 'Kubernetes/models/storage-class/models';
|
||||
import filesizeParser from 'filesize-parser';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
|
||||
class KubernetesVolumeController {
|
||||
/* @ngInject */
|
||||
|
@ -14,7 +15,6 @@ class KubernetesVolumeController {
|
|||
LocalStorage,
|
||||
KubernetesVolumeService,
|
||||
KubernetesEventService,
|
||||
KubernetesNamespaceHelper,
|
||||
KubernetesApplicationService,
|
||||
KubernetesPersistentVolumeClaimService,
|
||||
ModalService,
|
||||
|
@ -27,7 +27,6 @@ class KubernetesVolumeController {
|
|||
|
||||
this.KubernetesVolumeService = KubernetesVolumeService;
|
||||
this.KubernetesEventService = KubernetesEventService;
|
||||
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
|
||||
this.KubernetesApplicationService = KubernetesApplicationService;
|
||||
this.KubernetesPersistentVolumeClaimService = KubernetesPersistentVolumeClaimService;
|
||||
this.ModalService = ModalService;
|
||||
|
@ -55,7 +54,7 @@ class KubernetesVolumeController {
|
|||
}
|
||||
|
||||
isSystemNamespace() {
|
||||
return this.KubernetesNamespaceHelper.isSystemNamespace(this.volume.ResourcePool.Namespace.Name);
|
||||
return KubernetesNamespaceHelper.isSystemNamespace(this.volume.ResourcePool.Namespace.Name);
|
||||
}
|
||||
|
||||
isUsed() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue