feat(configurations): portainer k8s configurations lingo update for explicitness EE-1626 (#5722)

* kubernetes sidebar configuration lingo updated

* configurations list view updated

* updated configurations list add config button

* - updated create and update configuration buttons to display type of configuration being created/updated
- configuration filter displays explicit configuration type

* updated create configuration sub-title

* add configmap wording update

* portainer service lingo updated in k8s app creation and update forms

* publishing mode text updates

* KubernetesApplicationPublishingTypes updated INTERNAL and CLUSTER to CLUSTER_IP and NODE_PORT respectively

* application ports datatable updated

* updated service and ingress lingo on application view page

* reduced spacing to fit in ConfigMaps & Secrets in sidenav for different screen res
pull/5790/head
zees-dev 2021-09-29 13:58:04 +13:00 committed by GitHub
parent 01529203f1
commit e3b6e4a1d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 546 additions and 519 deletions

View File

@ -287,7 +287,7 @@ json-tree .branch-preview {
margin-top: 15px; margin-top: 15px;
} }
.summary { .bold {
color: var(--text-summary-color); color: var(--text-summary-color);
font-weight: 700; font-weight: 700;
} }

View File

@ -125,7 +125,7 @@
<td> <td>
<!-- LB --> <!-- LB -->
<span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.LOAD_BALANCER"> <span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.LOAD_BALANCER">
<span> <i class="fa fa-project-diagram" aria-hidden="true" style="margin-right: 2px;"></i> Load balancer </span> <span> <i class="fa fa-project-diagram" aria-hidden="true" style="margin-right: 2px;"></i> LoadBalancer </span>
<span class="text-muted small" style="margin-left: 5px;"> <span class="text-muted small" style="margin-left: 5px;">
<span ng-if="item.LoadBalancerIPAddress">{{ item.LoadBalancerIPAddress }}</span> <span ng-if="item.LoadBalancerIPAddress">{{ item.LoadBalancerIPAddress }}</span>
<span ng-if="!item.LoadBalancerIPAddress">pending</span> <span ng-if="!item.LoadBalancerIPAddress">pending</span>
@ -133,10 +133,10 @@
</span> </span>
<!-- Internal --> <!-- Internal -->
<span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.CLUSTER_IP"> <span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.CLUSTER_IP">
<i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i> Internal <i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i> ClusterIP
</span> </span>
<!-- Cluster --> <!-- Cluster -->
<span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.NODE_PORT"> <i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i> Cluster </span> <span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.NODE_PORT"> <i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i> NodePort </span>
</td> </td>
<!-- Exposed port --> <!-- Exposed port -->
<td> <td>

View File

@ -67,7 +67,7 @@
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove <i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button> </button>
<button type="button" class="btn btn-sm btn-primary" ui-sref="kubernetes.configurations.new" data-cy="k8sConfig-addConfigWithFormButton"> <button type="button" class="btn btn-sm btn-primary" ui-sref="kubernetes.configurations.new" data-cy="k8sConfig-addConfigWithFormButton">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add configuration with form <i class="fa fa-plus space-right" aria-hidden="true"></i>Add with form
</button> </button>
<button type="button" class="btn btn-sm btn-primary" ui-sref="kubernetes.deploy" data-cy="k8sConfig-deployFromManifestButton"> <button type="button" class="btn btn-sm btn-primary" ui-sref="kubernetes.deploy" data-cy="k8sConfig-deployFromManifestButton">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Create from manifest <i class="fa fa-plus space-right" aria-hidden="true"></i>Create from manifest

View File

@ -49,7 +49,7 @@
class-name="sidebar-list" class-name="sidebar-list"
data-cy="k8sSidebar-configurations" data-cy="k8sSidebar-configurations"
> >
Configurations ConfigMaps & Secrets
</sidebar-menu-item> </sidebar-menu-item>
<sidebar-menu-item path="kubernetes.volumes" path-params="{ endpointId: $ctrl.endpointId }" icon-class="fa-database fa-fw" class-name="sidebar-list" data-cy="k8sSidebar-volumes"> <sidebar-menu-item path="kubernetes.volumes" path-params="{ endpointId: $ctrl.endpointId }" icon-class="fa-database fa-fw" class-name="sidebar-list" data-cy="k8sSidebar-volumes">

View File

@ -299,11 +299,11 @@ class KubernetesApplicationConverter {
if (app.ServiceType === KubernetesServiceTypes.LOAD_BALANCER) { if (app.ServiceType === KubernetesServiceTypes.LOAD_BALANCER) {
res.PublishingType = KubernetesApplicationPublishingTypes.LOAD_BALANCER; res.PublishingType = KubernetesApplicationPublishingTypes.LOAD_BALANCER;
} else if (app.ServiceType === KubernetesServiceTypes.NODE_PORT) { } else if (app.ServiceType === KubernetesServiceTypes.NODE_PORT) {
res.PublishingType = KubernetesApplicationPublishingTypes.CLUSTER; res.PublishingType = KubernetesApplicationPublishingTypes.NODE_PORT;
} else if (app.ServiceType === KubernetesServiceTypes.CLUSTER_IP && isIngress) { } else if (app.ServiceType === KubernetesServiceTypes.CLUSTER_IP && isIngress) {
res.PublishingType = KubernetesApplicationPublishingTypes.INGRESS; res.PublishingType = KubernetesApplicationPublishingTypes.INGRESS;
} else { } else {
res.PublishingType = KubernetesApplicationPublishingTypes.INTERNAL; res.PublishingType = KubernetesApplicationPublishingTypes.CLUSTER_IP;
} }
if (app.Pods && app.Pods.length) { if (app.Pods && app.Pods.length) {

View File

@ -42,7 +42,7 @@ class KubernetesServiceConverter {
res.StackName = formValues.StackName ? formValues.StackName : formValues.Name; res.StackName = formValues.StackName ? formValues.StackName : formValues.Name;
res.ApplicationOwner = formValues.ApplicationOwner; res.ApplicationOwner = formValues.ApplicationOwner;
res.ApplicationName = formValues.Name; res.ApplicationName = formValues.Name;
if (formValues.PublishingType === KubernetesApplicationPublishingTypes.CLUSTER) { if (formValues.PublishingType === KubernetesApplicationPublishingTypes.NODE_PORT) {
res.Type = KubernetesServiceTypes.NODE_PORT; res.Type = KubernetesServiceTypes.NODE_PORT;
} else if (formValues.PublishingType === KubernetesApplicationPublishingTypes.LOAD_BALANCER) { } else if (formValues.PublishingType === KubernetesApplicationPublishingTypes.LOAD_BALANCER) {
res.Type = KubernetesServiceTypes.LOAD_BALANCER; res.Type = KubernetesServiceTypes.LOAD_BALANCER;

View File

@ -1,6 +1,5 @@
import _ from 'lodash-es'; import _ from 'lodash-es';
import { KubernetesApplicationDataAccessPolicies } from 'Kubernetes/models/application/models'; import { KubernetesApplicationDataAccessPolicies } from 'Kubernetes/models/application/models';
import { KubernetesServiceTypes } from 'Kubernetes/models/service/models';
import { KubernetesApplicationTypes, KubernetesApplicationTypeStrings } from 'Kubernetes/models/application/models'; import { KubernetesApplicationTypes, KubernetesApplicationTypeStrings } from 'Kubernetes/models/application/models';
import { KubernetesPodNodeAffinityNodeSelectorRequirementOperators } from 'Kubernetes/pod/models'; import { KubernetesPodNodeAffinityNodeSelectorRequirementOperators } from 'Kubernetes/pod/models';
@ -26,24 +25,11 @@ angular
var status = _.toLower(text); var status = _.toLower(text);
switch (status) { switch (status) {
case 'loadbalancer': case 'loadbalancer':
return 'Load balancer'; return 'LoadBalancer';
case 'clusterip': case 'clusterip':
return 'Internal'; return 'ClusterIP';
case 'nodeport': case 'nodeport':
return 'Cluster'; return 'NodePort';
}
};
})
.filter('kubernetesApplicationPortsTableHeaderText', function () {
'use strict';
return function (serviceType) {
switch (serviceType) {
case KubernetesServiceTypes.LOAD_BALANCER:
return 'Load balancer';
case KubernetesServiceTypes.CLUSTER_IP:
return 'Application';
case KubernetesServiceTypes.NODE_PORT:
return 'Cluster node';
} }
}; };
}) })

View File

@ -5,9 +5,9 @@ angular.module('portainer.kubernetes').filter('kubernetesConfigurationTypeText',
return function (type) { return function (type) {
switch (type) { switch (type) {
case KubernetesConfigurationTypes.SECRET: case KubernetesConfigurationTypes.SECRET:
return 'Sensitive'; return 'Secret';
case KubernetesConfigurationTypes.CONFIGMAP: case KubernetesConfigurationTypes.CONFIGMAP:
return 'Non-sensitive'; return 'ConfigMap';
} }
}; };
}); });

View File

@ -22,7 +22,7 @@ export function KubernetesApplicationFormValues() {
this.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.SHARED; this.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.SHARED;
this.PersistedFolders = []; // KubernetesApplicationPersistedFolderFormValue lis; this.PersistedFolders = []; // KubernetesApplicationPersistedFolderFormValue lis;
this.Configurations = []; // KubernetesApplicationConfigurationFormValue lis; this.Configurations = []; // KubernetesApplicationConfigurationFormValue lis;
this.PublishingType = KubernetesApplicationPublishingTypes.INTERNAL; this.PublishingType = KubernetesApplicationPublishingTypes.CLUSTER_IP;
this.PublishedPorts = []; // KubernetesApplicationPublishedPortFormValue lis; this.PublishedPorts = []; // KubernetesApplicationPublishedPortFormValue lis;
this.PlacementType = KubernetesApplicationPlacementTypes.PREFERRED; this.PlacementType = KubernetesApplicationPlacementTypes.PREFERRED;
this.Placements = []; // KubernetesApplicationPlacementFormValue lis; this.Placements = []; // KubernetesApplicationPlacementFormValue lis;

View File

@ -25,8 +25,8 @@ export const KubernetesApplicationTypeStrings = Object.freeze({
}); });
export const KubernetesApplicationPublishingTypes = Object.freeze({ export const KubernetesApplicationPublishingTypes = Object.freeze({
INTERNAL: 1, CLUSTER_IP: 1,
CLUSTER: 2, NODE_PORT: 2,
LOAD_BALANCER: 3, LOAD_BALANCER: 3,
INGRESS: 4, INGRESS: 4,
}); });

View File

@ -1238,6 +1238,19 @@
Publishing the application Publishing the application
</div> </div>
<!-- #region PUBLISHING OPTIONS --> <!-- #region PUBLISHING OPTIONS -->
<div class="form-group">
<div class="col-sm-12">
<label for="enable_port_publishing" class="control-label text-left">
Enable publishing for this application
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" class="form-control" name="enable_port_publishing" ng-model="ctrl.formValues.IsPublishingService" />
<i></i>
</label>
</div>
</div>
<span ng-if="ctrl.formValues.IsPublishingService">
<div class="form-group"> <div class="form-group">
<div class="col-sm-12 small text-muted"> <div class="col-sm-12 small text-muted">
Select how you want to publish your application. Select how you want to publish your application.
@ -1251,7 +1264,7 @@
<input <input
type="radio" type="radio"
id="publishing_internal" id="publishing_internal"
ng-value="ctrl.ApplicationPublishingTypes.INTERNAL" ng-value="ctrl.ApplicationPublishingTypes.CLUSTER_IP"
ng-model="ctrl.formValues.PublishingType" ng-model="ctrl.formValues.PublishingType"
ng-change="ctrl.onChangePublishedPorts()" ng-change="ctrl.onChangePublishedPorts()"
ng-disabled="ctrl.isPublishingTypeEditDisabled()" ng-disabled="ctrl.isPublishingTypeEditDisabled()"
@ -1261,18 +1274,18 @@
for="publishing_internal" for="publishing_internal"
ng-if=" ng-if="
!ctrl.isPublishingTypeEditDisabled() || !ctrl.isPublishingTypeEditDisabled() ||
(ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INTERNAL) (ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER_IP)
" "
> >
<div class="boxselector_header"> <div class="boxselector_header">
<i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i>
Internal ClusterIP
</div> </div>
<p>Internal communications inside the cluster only</p> <p>Internal communications inside the cluster only</p>
</label> </label>
<label <label
for="publishing_internal" for="publishing_internal"
ng-if="ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType !== ctrl.ApplicationPublishingTypes.INTERNAL" ng-if="ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType !== ctrl.ApplicationPublishingTypes.CLUSTER_IP"
tooltip-append-to-body="true" tooltip-append-to-body="true"
tooltip-placement="bottom" tooltip-placement="bottom"
tooltip-class="portainer-tooltip" tooltip-class="portainer-tooltip"
@ -1281,7 +1294,7 @@
> >
<div class="boxselector_header"> <div class="boxselector_header">
<i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i>
Internal ClusterIP
</div> </div>
<p>Internal communications inside the cluster only</p> <p>Internal communications inside the cluster only</p>
</label> </label>
@ -1291,7 +1304,7 @@
<input <input
type="radio" type="radio"
id="publishing_cluster" id="publishing_cluster"
ng-value="ctrl.ApplicationPublishingTypes.CLUSTER" ng-value="ctrl.ApplicationPublishingTypes.NODE_PORT"
ng-model="ctrl.formValues.PublishingType" ng-model="ctrl.formValues.PublishingType"
ng-change="ctrl.onChangePublishedPorts()" ng-change="ctrl.onChangePublishedPorts()"
ng-disabled="ctrl.isPublishingTypeEditDisabled()" ng-disabled="ctrl.isPublishingTypeEditDisabled()"
@ -1301,18 +1314,18 @@
for="publishing_cluster" for="publishing_cluster"
ng-if=" ng-if="
!ctrl.isPublishingTypeEditDisabled() || !ctrl.isPublishingTypeEditDisabled() ||
(ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER) (ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.NODE_PORT)
" "
> >
<div class="boxselector_header"> <div class="boxselector_header">
<i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i>
Cluster NodePort
</div> </div>
<p>Publish this application via a port on all nodes of the cluster</p> <p>Publish this application via a port on all nodes of the cluster</p>
</label> </label>
<label <label
for="publishing_cluster" for="publishing_cluster"
ng-if="ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType !== ctrl.ApplicationPublishingTypes.CLUSTER" ng-if="ctrl.isPublishingTypeEditDisabled() && ctrl.formValues.PublishingType !== ctrl.ApplicationPublishingTypes.NODE_PORT"
tooltip-append-to-body="true" tooltip-append-to-body="true"
tooltip-placement="bottom" tooltip-placement="bottom"
tooltip-class="portainer-tooltip" tooltip-class="portainer-tooltip"
@ -1321,7 +1334,7 @@
> >
<div class="boxselector_header"> <div class="boxselector_header">
<i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i>
Cluster NodePort
</div> </div>
<p>Publish this application via a port on all nodes of the cluster</p> <p>Publish this application via a port on all nodes of the cluster</p>
</label> </label>
@ -1420,13 +1433,13 @@
<div <div
class="col-sm-12 small text-muted" class="col-sm-12 small text-muted"
style="margin-top: 15px;" style="margin-top: 15px;"
ng-if="ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER && ctrl.formValues.PublishedPorts.length > 0" ng-if="ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.NODE_PORT && ctrl.formValues.PublishedPorts.length > 0"
> >
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
When publishing a port in cluster mode, the node port is optional. If left empty Kubernetes will use a random port number. If you wish to specify a port, use a When publishing a port in cluster mode, the node port is optional. If left empty Kubernetes will use a random port number. If you wish to specify a port, use
port number inside the default range <code>30000-32767</code>. a port number inside the default range <code>30000-32767</code>.
</div> </div>
<div ng-if="ctrl.isNotInternalAndHasNoPublishedPorts()" class="col-sm-12 small text-warning" style="margin-top: 12px;"> <div ng-if="ctrl.hasNoPublishedPorts()" class="col-sm-12 small text-warning" style="margin-top: 12px;">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> At least one published port must be defined. <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> At least one published port must be defined.
</div> </div>
@ -1469,8 +1482,8 @@
class="col-sm-3 input-group input-group-sm" class="col-sm-3 input-group input-group-sm"
ng-class="{ striked: publishedPort.NeedsDeletion }" ng-class="{ striked: publishedPort.NeedsDeletion }"
ng-if=" ng-if="
(publishedPort.IsNew && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER) || (publishedPort.IsNew && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.NODE_PORT) ||
(!publishedPort.IsNew && ctrl.savedFormValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER) (!publishedPort.IsNew && ctrl.savedFormValues.PublishingType === ctrl.ApplicationPublishingTypes.NODE_PORT)
" "
> >
<span class="input-group-addon">node port</span> <span class="input-group-addon">node port</span>
@ -1633,7 +1646,8 @@
kubernetesApplicationCreationForm['ingress_class_' + $index].$invalid || kubernetesApplicationCreationForm['ingress_class_' + $index].$invalid ||
kubernetesApplicationCreationForm['ingress_route_' + $index].$invalid || kubernetesApplicationCreationForm['ingress_route_' + $index].$invalid ||
ctrl.state.duplicates.publishedPorts.containerPorts.refs[$index] !== undefined || ctrl.state.duplicates.publishedPorts.containerPorts.refs[$index] !== undefined ||
(ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER && ctrl.state.duplicates.publishedPorts.nodePorts.refs[$index] !== undefined) || (ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.NODE_PORT &&
ctrl.state.duplicates.publishedPorts.nodePorts.refs[$index] !== undefined) ||
(ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS && (ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS &&
ctrl.state.duplicates.publishedPorts.ingressRoutes.refs[$index] !== undefined) || ctrl.state.duplicates.publishedPorts.ingressRoutes.refs[$index] !== undefined) ||
(ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.LOAD_BALANCER && (ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.LOAD_BALANCER &&
@ -1645,7 +1659,8 @@
class="small text-warning" class="small text-warning"
style="margin-top: 5px;" style="margin-top: 5px;"
ng-if=" ng-if="
kubernetesApplicationCreationForm['container_port_' + $index].$invalid || ctrl.state.duplicates.publishedPorts.containerPorts.refs[$index] !== undefined kubernetesApplicationCreationForm['container_port_' + $index].$invalid ||
ctrl.state.duplicates.publishedPorts.containerPorts.refs[$index] !== undefined
" "
> >
<div ng-messages="kubernetesApplicationCreationForm['container_port_'+$index].$error"> <div ng-messages="kubernetesApplicationCreationForm['container_port_'+$index].$error">
@ -1659,12 +1674,13 @@
</div> </div>
</div> </div>
<div class="col-sm-3 input-group input-group-sm" ng-if="ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.CLUSTER"> <div class="col-sm-3 input-group input-group-sm" ng-if="ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.NODE_PORT">
<div <div
class="small text-warning" class="small text-warning"
style="margin-top: 5px;" style="margin-top: 5px;"
ng-if=" ng-if="
kubernetesApplicationCreationForm['published_node_port_' + $index].$invalid || ctrl.state.duplicates.publishedPorts.nodePorts.refs[$index] !== undefined kubernetesApplicationCreationForm['published_node_port_' + $index].$invalid ||
ctrl.state.duplicates.publishedPorts.nodePorts.refs[$index] !== undefined
" "
> >
<div ng-messages="kubernetesApplicationCreationForm['published_node_port_'+$index].$error"> <div ng-messages="kubernetesApplicationCreationForm['published_node_port_'+$index].$error">
@ -1695,8 +1711,8 @@
<div ng-messages="kubernetesApplicationCreationForm['ingress_route_'+$index].$error"> <div ng-messages="kubernetesApplicationCreationForm['ingress_route_'+$index].$error">
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Route is required.</p> <p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Route is required.</p>
<p ng-message="pattern" <p ng-message="pattern"
><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field must consist of alphanumeric characters or the special characters: '-', '_' ><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field must consist of alphanumeric characters or the special characters: '-',
or '/'. It must start and end with an alphanumeric character (e.g. 'my-route', or 'route-123').</p '_' or '/'. It must start and end with an alphanumeric character (e.g. 'my-route', or 'route-123').</p
> >
</div> </div>
<p ng-if="ctrl.state.duplicates.publishedPorts.ingressRoutes.refs[$index] !== undefined"> <p ng-if="ctrl.state.duplicates.publishedPorts.ingressRoutes.refs[$index] !== undefined">
@ -1731,6 +1747,7 @@
<!-- #endregion --> <!-- #endregion -->
</div> </div>
</div> </div>
</span>
<!-- #endregion --> <!-- #endregion -->
<!-- summary --> <!-- summary -->

View File

@ -37,6 +37,7 @@ class KubernetesCreateApplicationController {
/* @ngInject */ /* @ngInject */
constructor( constructor(
$scope,
$async, $async,
$state, $state,
Notifications, Notifications,
@ -54,6 +55,7 @@ class KubernetesCreateApplicationController {
StackService, StackService,
KubernetesNodesLimitsService KubernetesNodesLimitsService
) { ) {
this.$scope = $scope;
this.$async = $async; this.$async = $async;
this.$state = $state; this.$state = $state;
this.Notifications = Notifications; this.Notifications = Notifications;
@ -140,6 +142,9 @@ class KubernetesCreateApplicationController {
this.deployApplicationAsync = this.deployApplicationAsync.bind(this); this.deployApplicationAsync = this.deployApplicationAsync.bind(this);
this.setPullImageValidity = this.setPullImageValidity.bind(this); this.setPullImageValidity = this.setPullImageValidity.bind(this);
this.onChangeFileContent = this.onChangeFileContent.bind(this); this.onChangeFileContent = this.onChangeFileContent.bind(this);
this.onServicePublishChange = this.onServicePublishChange.bind(this);
this.$scope.$watch(() => this.formValues.IsPublishingService, this.onServicePublishChange);
} }
/* #endregion */ /* #endregion */
@ -416,6 +421,27 @@ class KubernetesCreateApplicationController {
/* #endregion */ /* #endregion */
onServicePublishChange() {
// service creation
if (this.formValues.PublishedPorts.length === 0) {
if (this.formValues.IsPublishingService) {
// toggle enabled
this.addPublishedPort();
}
return;
}
// service update
if (this.formValues.IsPublishingService) {
// toggle enabled
this.formValues.PublishedPorts.forEach((port) => (port.NeedsDeletion = false));
} else {
// toggle disabled
// all new ports need to be deleted, existing ports need to be marked as needing deletion
this.formValues.PublishedPorts = this.formValues.PublishedPorts.filter((port) => !port.IsNew).map((port) => ({ ...port, NeedsDeletion: true }));
}
}
/* #region PUBLISHED PORTS UI MANAGEMENT */ /* #region PUBLISHED PORTS UI MANAGEMENT */
addPublishedPort() { addPublishedPort() {
const p = new KubernetesApplicationPublishedPortFormValue(); const p = new KubernetesApplicationPublishedPortFormValue();
@ -476,7 +502,7 @@ class KubernetesCreateApplicationController {
onChangePortMappingNodePort() { onChangePortMappingNodePort() {
const state = this.state.duplicates.publishedPorts.nodePorts; const state = this.state.duplicates.publishedPorts.nodePorts;
if (this.formValues.PublishingType === KubernetesApplicationPublishingTypes.CLUSTER) { if (this.formValues.PublishingType === KubernetesApplicationPublishingTypes.NODE_PORT) {
const source = _.map(this.formValues.PublishedPorts, (p) => (p.NeedsDeletion ? undefined : p.NodePort)); const source = _.map(this.formValues.PublishedPorts, (p) => (p.NeedsDeletion ? undefined : p.NodePort));
const duplicates = KubernetesFormValidationHelper.getDuplicates(source); const duplicates = KubernetesFormValidationHelper.getDuplicates(source);
state.refs = duplicates; state.refs = duplicates;
@ -736,10 +762,8 @@ class KubernetesCreateApplicationController {
return this.state.isEdit && !this.formValues.PublishedPorts[index].IsNew; return this.state.isEdit && !this.formValues.PublishedPorts[index].IsNew;
} }
isNotInternalAndHasNoPublishedPorts() { hasNoPublishedPorts() {
const toDelPorts = _.filter(this.formValues.PublishedPorts, { NeedsDeletion: true }); return this.formValues.PublishedPorts.filter((port) => !port.NeedsDeletion).length === 0;
const toKeepPorts = _.without(this.formValues.PublishedPorts, ...toDelPorts);
return this.formValues.PublishingType !== KubernetesApplicationPublishingTypes.INTERNAL && toKeepPorts.length === 0;
} }
isEditAndNotNewPlacement(index) { isEditAndNotNewPlacement(index) {
@ -771,8 +795,8 @@ class KubernetesCreateApplicationController {
const invalid = !this.isValid(); const invalid = !this.isValid();
const hasNoChanges = this.isEditAndNoChangesMade(); const hasNoChanges = this.isEditAndNoChangesMade();
const nonScalable = this.isNonScalable(); const nonScalable = this.isNonScalable();
const notInternalNoPorts = this.isNotInternalAndHasNoPublishedPorts(); const isPublishingWithoutPorts = this.formValues.IsPublishingService && this.hasNoPublishedPorts();
return overflow || autoScalerOverflow || inProgress || invalid || hasNoChanges || nonScalable || notInternalNoPorts; return overflow || autoScalerOverflow || inProgress || invalid || hasNoChanges || nonScalable || isPublishingWithoutPorts;
} }
disableLoadBalancerEdit() { disableLoadBalancerEdit() {
@ -926,7 +950,7 @@ class KubernetesCreateApplicationController {
if (this.savedFormValues) { if (this.savedFormValues) {
this.formValues.PublishingType = this.savedFormValues.PublishingType; this.formValues.PublishingType = this.savedFormValues.PublishingType;
} else { } else {
this.formValues.PublishingType = this.ApplicationPublishingTypes.INTERNAL; this.formValues.PublishingType = this.ApplicationPublishingTypes.CLUSTER_IP;
} }
} }
this.formValues.OriginalIngresses = this.ingresses; this.formValues.OriginalIngresses = this.ingresses;
@ -1114,6 +1138,8 @@ class KubernetesCreateApplicationController {
this.nodesLimits.excludesPods(this.application.Pods, this.formValues.CpuLimit, KubernetesResourceReservationHelper.bytesValue(this.formValues.MemoryLimit)); this.nodesLimits.excludesPods(this.application.Pods, this.formValues.CpuLimit, KubernetesResourceReservationHelper.bytesValue(this.formValues.MemoryLimit));
} }
this.formValues.IsPublishingService = this.formValues.PublishedPorts.length > 0;
this.updateNamespaceLimits(); this.updateNamespaceLimits();
this.updateSliders(); this.updateSliders();
} catch (err) { } catch (err) {

View File

@ -253,7 +253,8 @@
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.LOAD_BALANCER"> <div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.LOAD_BALANCER">
<div class="small text-muted"> <div class="small text-muted">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application is exposed through an external load balancer. Use the links below to access the different ports exposed. This application is exposed through a service of type <span class="bold">{{ ctrl.application.ServiceType }}</span
>. Refer to the port configuration below to access it.
</div> </div>
<div style="margin-top: 10px;" class="small text-muted"> <div style="margin-top: 10px;" class="small text-muted">
<span ng-if="!ctrl.application.LoadBalancerIPAddress"> <span ng-if="!ctrl.application.LoadBalancerIPAddress">
@ -282,45 +283,41 @@
</div> </div>
</div> </div>
<!-- cluster notice --> <!-- NodePort notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.NODE_PORT"> <div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.NODE_PORT">
<div class="small text-muted"> <div class="small text-muted">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application is exposed globally on all nodes of your cluster. It can be reached using the IP address of any node in your cluster using the port configuration This application is exposed through a service of type <span class="bold">{{ ctrl.application.ServiceType }}</span
below. >. It can be reached using the IP address of any node in your cluster using the port configuration below.
</div> </div>
</div> </div>
<!-- internal notice --> <!-- ClusterIP notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.CLUSTER_IP && !ctrl.state.useIngress"> <div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.CLUSTER_IP && !ctrl.state.useIngress">
<div class="small text-muted"> <div class="small text-muted">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application is only available for internal usage inside the cluster via the application name <code>{{ ctrl.application.ServiceName }}</code> This application is exposed through a service of type <span class="bold">{{ ctrl.application.ServiceType }}</span
>. It can be reached via the application name <code>{{ ctrl.application.ServiceName }}</code> and the port configuration below.
<span class="btn btn-primary btn-xs" ng-click="ctrl.copyApplicationName()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span> <span class="btn btn-primary btn-xs" ng-click="ctrl.copyApplicationName()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span>
<span id="copyNotificationApplicationName" style="margin-left: 7px; display: none; color: #23ae89;" class="small" <span id="copyNotificationApplicationName" style="margin-left: 7px; display: none; color: #23ae89;" class="small"
><i class="fa fa-check" aria-hidden="true"></i> copied</span ><i class="fa fa-check" aria-hidden="true"></i> copied</span
> >
</div> </div>
<div class="small text-muted" style="margin-top: 2px;">
<p>Refer to the below port configuration to access the application.</p>
</div>
</div> </div>
<!-- ingress notice --> <!-- Ingress notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.CLUSTER_IP && ctrl.state.useIngress"> <div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.CLUSTER_IP && ctrl.state.useIngress">
<div class="small text-muted"> <div class="small text-muted">
<p> <p>
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application is available for internal usage inside the cluster via the application name <code>{{ ctrl.application.ServiceName }}</code> This application is exposed through a service of type <span class="bold">{{ ctrl.application.ServiceType }}</span
>. It can be reached via the application name <code>{{ ctrl.application.ServiceName }}</code> and the port configuration below.
<span class="btn btn-primary btn-xs" ng-click="ctrl.copyApplicationName()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span> <span class="btn btn-primary btn-xs" ng-click="ctrl.copyApplicationName()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span>
<span id="copyNotificationApplicationName" style="margin-left: 7px; display: none; color: #23ae89;" class="small" <span id="copyNotificationApplicationName" style="margin-left: 7px; display: none; color: #23ae89;" class="small"
><i class="fa fa-check" aria-hidden="true"></i> copied</span ><i class="fa fa-check" aria-hidden="true"></i> copied</span
> >
</p> </p>
<p>It can also be accessed via specific HTTP route(s).</p> <p>It is also associated to an <span class="bold">Ingress</span> and can be accessed via specific HTTP route(s).</p>
</div>
<div class="small text-muted" style="margin-top: 2px;">
<p>Refer to the below port configuration to access the application.</p>
</div> </div>
</div> </div>
@ -330,7 +327,7 @@
<tbody> <tbody>
<tr class="text-muted"> <tr class="text-muted">
<td style="width: 25%;">Container port</td> <td style="width: 25%;">Container port</td>
<td style="width: 25%;">{{ ctrl.application.ServiceType | kubernetesApplicationPortsTableHeaderText }} port</td> <td style="width: 25%;">Service port</td>
<td style="width: 50%;">HTTP route</td> <td style="width: 50%;">HTTP route</td>
</tr> </tr>
<tr ng-repeat-start="port in ctrl.application.PublishedPorts"> <tr ng-repeat-start="port in ctrl.application.PublishedPorts">

View File

@ -1,5 +1,5 @@
<kubernetes-view-header title="Configuration list" state="kubernetes.configurations" view-ready="ctrl.state.viewReady"> <kubernetes-view-header title="ConfigMaps & Secrets list" state="kubernetes.configurations" view-ready="ctrl.state.viewReady">
Configurations ConfigMaps & Secrets
</kubernetes-view-header> </kubernetes-view-header>
<kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading> <kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading>

View File

@ -1,5 +1,5 @@
<kubernetes-view-header title="Create configuration" state="kubernetes.configurations.new" view-ready="ctrl.state.viewReady"> <kubernetes-view-header title="Create configuration" state="kubernetes.configurations.new" view-ready="ctrl.state.viewReady">
<a ui-sref="kubernetes.configurations">Configurations</a> &gt; Create a configuration <a ui-sref="kubernetes.configurations">ConfigMaps and Secrets</a> &gt; Create a configuration
</kubernetes-view-header> </kubernetes-view-header>
<kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading> <kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading>
@ -95,7 +95,7 @@
<label for="type_basic" data-cy="k8sConfigCreate-nonSensitiveButton"> <label for="type_basic" data-cy="k8sConfigCreate-nonSensitiveButton">
<div class="boxselector_header"> <div class="boxselector_header">
<i class="fa fa-file-code" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-file-code" aria-hidden="true" style="margin-right: 2px;"></i>
Non-sensitive ConfigMap
</div> </div>
<p>This configuration holds non-sensitive information</p> <p>This configuration holds non-sensitive information</p>
</label> </label>
@ -105,7 +105,7 @@
<label for="type_secret" data-cy="k8sConfigCreate-sensitiveButton"> <label for="type_secret" data-cy="k8sConfigCreate-sensitiveButton">
<div class="boxselector_header"> <div class="boxselector_header">
<i class="fa fa-user-secret" aria-hidden="true" style="margin-right: 2px;"></i> <i class="fa fa-user-secret" aria-hidden="true" style="margin-right: 2px;"></i>
Sensitive Secret
</div> </div>
<p>This configuration holds sensitive information</p> <p>This configuration holds sensitive information</p>
</label> </label>
@ -153,7 +153,7 @@
button-spinner="ctrl.state.actionInProgress" button-spinner="ctrl.state.actionInProgress"
data-cy="k8sConfigCreate-CreateConfigButton" data-cy="k8sConfigCreate-CreateConfigButton"
> >
<span ng-hide="ctrl.state.actionInProgress">Create configuration</span> <span ng-hide="ctrl.state.actionInProgress">Create {{ ctrl.formValues.Type | kubernetesConfigurationTypeText }}</span>
<span ng-show="ctrl.state.actionInProgress">Creation in progress...</span> <span ng-show="ctrl.state.actionInProgress">Creation in progress...</span>
</button> </button>
</div> </div>

View File

@ -1,7 +1,7 @@
<kubernetes-view-header title="Configuration details" state="kubernetes.configurations.configuration" view-ready="ctrl.state.viewReady"> <kubernetes-view-header title="Configuration details" state="kubernetes.configurations.configuration" view-ready="ctrl.state.viewReady">
<a ui-sref="kubernetes.resourcePools">Namespaces</a> &gt; <a ui-sref="kubernetes.resourcePools">Namespaces</a> &gt;
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: ctrl.configuration.Namespace })">{{ ctrl.configuration.Namespace }}</a> &gt; <a ui-sref="kubernetes.resourcePools.resourcePool({ id: ctrl.configuration.Namespace })">{{ ctrl.configuration.Namespace }}</a> &gt;
<a ui-sref="kubernetes.configurations">Configurations</a> &gt; {{ ctrl.configuration.Name }} <a ui-sref="kubernetes.configurations">ConfigMaps and Secrets</a> &gt; {{ ctrl.configuration.Name }}
</kubernetes-view-header> </kubernetes-view-header>
<kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading> <kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading>
@ -106,7 +106,7 @@
button-spinner="ctrl.state.actionInProgress" button-spinner="ctrl.state.actionInProgress"
data-cy="k8sConfigDetail-updateConfig" data-cy="k8sConfigDetail-updateConfig"
> >
<span ng-hide="ctrl.state.actionInProgress">Update configuration</span> <span ng-hide="ctrl.state.actionInProgress">Update {{ ctrl.configuration.Type | kubernetesConfigurationTypeText }}</span>
<span ng-show="ctrl.state.actionInProgress">Update in progress...</span> <span ng-show="ctrl.state.actionInProgress">Update in progress...</span>
</button> </button>
</div> </div>

View File

@ -22,7 +22,7 @@
<li ng-repeat="summary in $ctrl.state.resources" ng-if="summary.action && summary.kind && summary.name"> <li ng-repeat="summary in $ctrl.state.resources" ng-if="summary.action && summary.kind && summary.name">
{{ summary.action }} {{ summary.action }}
{{ $ctrl.getArticle(summary.kind, summary.action) }} {{ $ctrl.getArticle(summary.kind, summary.action) }}
<span class="summary">{{ summary.kind }}</span> named <code>{{ summary.name }}</code> <span class="bold">{{ summary.kind }}</span> named <code>{{ summary.name }}</code>
<span ng-if="summary.type"> <span ng-if="summary.type">
of type <code>{{ summary.type }}</code></span of type <code>{{ summary.type }}</code></span
> >

View File

@ -271,6 +271,7 @@ ul.sidebar .sidebar-title .form-control {
ul.sidebar .sidebar-list a, ul.sidebar .sidebar-list a,
ul.sidebar .sidebar-list .sidebar-sublist a { ul.sidebar .sidebar-list .sidebar-sublist a {
line-height: 36px; line-height: 36px;
letter-spacing: -0.03em;
} }
ul.sidebar .sidebar-list .menu-icon { ul.sidebar .sidebar-list .menu-icon {