mirror of
https://github.com/portainer/portainer.git
synced 2025-07-23 15:29:42 +02:00
feat(kubernetes): add ingress details (#4013)
* feat(kubernetes): add ingress details * fix(kubernetes): fix broken ingress generated links + ignore IP retrieval/display info on missing LB ingress ip * refactor(kubernetes): each ingress rule in apps port mappings has now its own row * feat(kubernetes): remove protocol column and concat it to container port * feat(kubernetes): edit display of ingress rules in application details * feat(kubernetes): minor UI update Co-authored-by: Anthony Lapenna <lapenna.anthony@gmail.com>
This commit is contained in:
parent
b09b1b1691
commit
1b3e2c8f69
19 changed files with 450 additions and 137 deletions
|
@ -96,15 +96,13 @@
|
|||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a ng-click="$ctrl.changeOrderBy('Protocol')">
|
||||
Protocol
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Protocol' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Protocol' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
HTTP route
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- main rows -->
|
||||
<!-- dir-paginate-start track by $index -->
|
||||
<tr
|
||||
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | filter: $ctrl.isDisplayed | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
|
||||
ng-class="{ active: item.Checked }"
|
||||
|
@ -112,40 +110,87 @@
|
|||
ng-click="$ctrl.expandItem(item, !item.Expanded)"
|
||||
pagination-id="$ctrl.tableKey"
|
||||
>
|
||||
<!-- expandable -->
|
||||
<td>
|
||||
<a ng-if="$ctrl.itemCanExpand(item)">
|
||||
<i ng-class="{ 'fas fa-angle-down': item.Expanded, 'fas fa-angle-right': !item.Expanded }" class="space-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</td>
|
||||
<!-- Application -->
|
||||
<td>
|
||||
<a ui-sref="kubernetes.applications.application({ name: item.Name, namespace: item.ResourcePool })">{{ item.Name }}</a>
|
||||
<span class="label label-info image-tag label-margins" ng-if="$ctrl.isSystemNamespace(item)">system</span>
|
||||
<span class="label label-primary image-tag label-margins" ng-if="!$ctrl.isSystemNamespace(item) && $ctrl.isExternalApplication(item)">external</span>
|
||||
</td>
|
||||
<!-- Publishing mode -->
|
||||
<td>
|
||||
<span ng-if="item.ServiceType === 'LoadBalancer'">
|
||||
<!-- LB -->
|
||||
<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 class="text-muted small" style="margin-left: 5px;">
|
||||
<span ng-if="item.LoadBalancerIPAddress">{{ item.LoadBalancerIPAddress }}</span>
|
||||
<span ng-if="!item.LoadBalancerIPAddress">pending</span>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-if="item.ServiceType === 'ClusterIP'"> <i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i> Internal </span>
|
||||
<span ng-if="item.ServiceType === 'NodePort'"> <i class="fa fa-list" aria-hidden="true" style="margin-right: 2px;"></i> Cluster </span>
|
||||
<!-- Internal -->
|
||||
<span ng-if="item.ServiceType === $ctrl.KubernetesServiceTypes.CLUSTER_IP">
|
||||
<i class="fa fa-list-alt" aria-hidden="true" style="margin-right: 2px;"></i> Internal
|
||||
</span>
|
||||
<!-- 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>
|
||||
</td>
|
||||
<td ng-if="!$ctrl.itemCanExpand(item)">
|
||||
{{ item.Ports[0].Port }}
|
||||
<a ng-if="item.LoadBalancerIPAddress" ng-href="http://{{ item.LoadBalancerIPAddress }}:{{ item.Ports[0].Port }}" target="_blank" style="margin-left: 5px;">
|
||||
<!-- Exposed port -->
|
||||
<td>
|
||||
<span ng-if="!$ctrl.itemCanExpand(item)">
|
||||
{{ item.Ports[0].Port }}
|
||||
<a ng-if="item.LoadBalancerIPAddress" ng-href="http://{{ item.LoadBalancerIPAddress }}:{{ item.Ports[0].Port }}" target="_blank" style="margin-left: 5px;">
|
||||
<i class="fa fa-external-link-alt" aria-hidden="true"></i> access
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
<!-- Container port -->
|
||||
<td>
|
||||
<span ng-if="!$ctrl.itemCanExpand(item)"> {{ item.Ports[0].TargetPort }}/{{ item.Ports[0].Protocol }} </span>
|
||||
</td>
|
||||
<!-- HTTP route -->
|
||||
<td>
|
||||
<span ng-if="!$ctrl.itemCanExpand(item)">
|
||||
<span ng-if="!$ctrl.portHasIngressRules(item.Ports[0])">-</span>
|
||||
<span ng-if="$ctrl.portHasIngressRules(item.Ports[0])">
|
||||
<span
|
||||
ng-if="!$ctrl.ruleCanBeDisplayed(item.Ports[0].IngressRules[0])"
|
||||
class="text-muted"
|
||||
tooltip-append-to-body="true"
|
||||
tooltip-placement="bottom"
|
||||
tooltip-class="portainer-tooltip"
|
||||
uib-tooltip="Ingress controller IP address not available yet"
|
||||
style="cursor: pointer;"
|
||||
>pending
|
||||
</span>
|
||||
<span ng-if="$ctrl.ruleCanBeDisplayed(item.Ports[0].IngressRules[0])">
|
||||
<a ng-href="{{ $ctrl.buildIngressRuleURL(item.Ports[0].IngressRules[0]) }}" target="_blank">
|
||||
{{ $ctrl.buildIngressRuleURL(item.Ports[0].IngressRules[0]) | stripprotocol }}
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- sub rows -->
|
||||
<tr ng-show="item.Expanded" ng-repeat-start="port in item.Ports" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
|
||||
<td ng-if="!$ctrl.portHasIngressRules(port)"></td>
|
||||
<td ng-if="!$ctrl.portHasIngressRules(port)">-</td>
|
||||
<td ng-if="!$ctrl.portHasIngressRules(port)">-</td>
|
||||
<td ng-if="!$ctrl.portHasIngressRules(port)">
|
||||
{{ port.Port }}
|
||||
<a ng-if="item.LoadBalancerIPAddress" ng-href="http://{{ item.LoadBalancerIPAddress }}:{{ port.Port }}" target="_blank" style="margin-left: 5px;">
|
||||
<i class="fa fa-external-link-alt" aria-hidden="true"></i> access
|
||||
</a>
|
||||
</td>
|
||||
<td ng-if="!$ctrl.itemCanExpand(item)">{{ item.Ports[0].TargetPort }}</td>
|
||||
<td ng-if="!$ctrl.itemCanExpand(item)">{{ item.Ports[0].Protocol }}</td>
|
||||
<td ng-if="$ctrl.itemCanExpand(item)"></td>
|
||||
<td ng-if="$ctrl.itemCanExpand(item)"></td>
|
||||
<td ng-if="$ctrl.itemCanExpand(item)"></td>
|
||||
<td ng-if="!$ctrl.portHasIngressRules(port)">{{ port.TargetPort }}/{{ port.Protocol }}</td>
|
||||
<td ng-if="!$ctrl.portHasIngressRules(port)">-</td>
|
||||
</tr>
|
||||
<tr dir-paginate-end ng-show="item.Expanded" ng-repeat="port in item.Ports" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
|
||||
<tr ng-show="item.Expanded" ng-repeat-end ng-repeat="rule in port.IngressRules" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
|
||||
<td></td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
|
@ -155,12 +200,31 @@
|
|||
<i class="fa fa-external-link-alt" aria-hidden="true"></i> access
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ port.TargetPort }}</td>
|
||||
<td>{{ port.Protocol }}</td>
|
||||
<td>{{ port.TargetPort }}/{{ port.Protocol }}</td>
|
||||
<td>
|
||||
<span
|
||||
ng-if="!$ctrl.ruleCanBeDisplayed(rule)"
|
||||
class="text-muted"
|
||||
tooltip-append-to-body="true"
|
||||
tooltip-placement="bottom"
|
||||
tooltip-class="portainer-tooltip"
|
||||
uib-tooltip="Ingress controller IP address not available yet"
|
||||
style="cursor: pointer;"
|
||||
>pending
|
||||
</span>
|
||||
<span ng-if="$ctrl.ruleCanBeDisplayed(rule)">
|
||||
<a ng-href="{{ $ctrl.buildIngressRuleURL(rule) }}" target="_blank">
|
||||
{{ $ctrl.buildIngressRuleURL(rule) | stripprotocol }}
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr dir-paginate-end></tr>
|
||||
<!-- no dataset -->
|
||||
<tr ng-if="!$ctrl.dataset">
|
||||
<td colspan="6" class="text-center text-muted">Loading...</td>
|
||||
</tr>
|
||||
<!-- no values in filtered dataset -->
|
||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0">
|
||||
<td colspan="6" class="text-center text-muted">No application port mapping available.</td>
|
||||
</tr>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import _ from 'lodash-es';
|
||||
import { KubernetesApplicationDeploymentTypes } from 'Kubernetes/models/application/models';
|
||||
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
|
||||
import { KubernetesServiceTypes } from 'Kubernetes/models/service/models';
|
||||
|
||||
angular.module('portainer.docker').controller('KubernetesApplicationsPortsDatatableController', [
|
||||
'$scope',
|
||||
|
@ -16,6 +17,7 @@ angular.module('portainer.docker').controller('KubernetesApplicationsPortsDatata
|
|||
});
|
||||
|
||||
var ctrl = this;
|
||||
this.KubernetesServiceTypes = KubernetesServiceTypes;
|
||||
|
||||
this.settings = Object.assign(this.settings, {
|
||||
showSystem: false,
|
||||
|
@ -49,7 +51,20 @@ angular.module('portainer.docker').controller('KubernetesApplicationsPortsDatata
|
|||
};
|
||||
|
||||
this.itemCanExpand = function (item) {
|
||||
return item.Ports.length > 1;
|
||||
return item.Ports.length > 1 || item.Ports[0].IngressRules.length > 1;
|
||||
};
|
||||
|
||||
this.buildIngressRuleURL = function (rule) {
|
||||
const hostname = rule.Host ? rule.Host : rule.IP;
|
||||
return 'http://' + hostname + rule.Path;
|
||||
};
|
||||
|
||||
this.portHasIngressRules = function (port) {
|
||||
return port.IngressRules.length > 0;
|
||||
};
|
||||
|
||||
this.ruleCanBeDisplayed = function (rule) {
|
||||
return !rule.Host && !rule.IP ? false : true;
|
||||
};
|
||||
|
||||
this.hasExpandableItems = function () {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue