portainer/app/kubernetes/views/applications/edit/application.html

601 lines
33 KiB
HTML

<kubernetes-view-header title="Application details" state="kubernetes.applications.application" view-ready="ctrl.state.viewReady">
<a ui-sref="kubernetes.resourcePools">Namespaces</a> &gt;
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: ctrl.application.ResourcePool })">{{ ctrl.application.ResourcePool }}</a> &gt;
<a ui-sref="kubernetes.applications">Applications</a> &gt; {{ ctrl.application.Name }}
</kubernetes-view-header>
<kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading>
<div ng-if="ctrl.state.viewReady">
<div class="row">
<div class="col-sm-12">
<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-heading> <i class="fa fa-laptop-code space-right" aria-hidden="true"></i> Application </uib-tab-heading>
<div style="padding: 20px;">
<table class="table">
<tbody>
<tr>
<td>Name</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>
</tr>
<tr>
<td>Stack</td>
<td>{{ ctrl.application.StackName || '-' }}</td>
</tr>
<tr>
<td>Namespace</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()">system</span>
</td>
</tr>
<tr>
<td>Application Type</td>
<td>
{{ ctrl.application.ApplicationType | kubernetesApplicationTypeText }}
</td>
</tr>
<tr>
<td>Status</td>
<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 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 }}
</td>
</tr>
<tr ng-if="ctrl.application.Requests.Cpu || ctrl.application.Requests.Memory">
<td>
<div>Resource reservations</div>
<div ng-if="ctrl.application.ApplicationType !== ctrl.KubernetesApplicationTypes.POD" class="text-muted small"> per instance </div>
</td>
<td>
<div ng-if="ctrl.application.Requests.Cpu">CPU {{ ctrl.application.Requests.Cpu | kubernetesApplicationCPUValue }}</div>
<div ng-if="ctrl.application.Requests.Memory">Memory {{ ctrl.application.Requests.Memory | humansize }}</div>
</td>
</tr>
<tr>
<td>Creation</td>
<td>
<span ng-if="ctrl.application.ApplicationOwner" style="margin-right: 5px;"> <i class="fas fa-user"></i> {{ ctrl.application.ApplicationOwner }} </span>
<span> <i class="fas fa-clock"></i> {{ ctrl.application.CreationDate | getisodate }}</span>
<span ng-if="ctrl.application.ApplicationOwner">
<i class="fa fa-file-code space-left space-right" aria-hidden="true"></i> Deployed from {{ ctrl.state.appType }}</span
>
</td>
</tr>
<tr>
<td colspan="2">
<form class="form-horizontal" name="kubernetesApplicationNoteForm">
<div class="form-group">
<div class="col-sm-12">
<i class="fa fa-edit" aria-hidden="true"></i> Note
<button class="btn btn-xs btn-primary" ng-click="ctrl.state.expandedNote = !ctrl.state.expandedNote;"
>{{ ctrl.state.expandedNote ? 'Collapse' : 'Expand' }}
<i class="fas {{ ctrl.state.expandedNote ? 'fa-angle-up' : 'fa-angle-down' }}" aria-hidden="true"></i
></button>
</div>
</div>
<div class="form-group" ng-if="ctrl.state.expandedNote">
<div class="col-sm-12">
<textarea
class="form-control"
name="application_note"
id="application_note"
ng-model="ctrl.formValues.Note"
rows="5"
placeholder="Enter a note about this application..."
></textarea>
</div>
</div>
<div class="form-group" ng-if="ctrl.state.expandedNote">
<div class="col-sm-12">
<button
class="btn btn-primary btn-sm"
style="margin-left: 0px;"
type="button"
ng-click="ctrl.updateApplication()"
ng-disabled="ctrl.formValues.Note === ctrl.application.Note"
>{{ ctrl.application.Note ? 'Update' : 'Save' }} note</button
>
</div>
</div>
</form>
</td>
</tr>
<!-- <tr>
<td colspan="2">
<form class="form-horizontal" name="KubernetesApplicationRollbackForm">
<div class="form-group">
<label for="resource-pool-selector" class="col-sm-2 col-lg-1 control-label text-left">Version</label>
<div class="col-sm-2">
<select class="form-control" id="resource-pool-selector" ng-model="ctrl.formValues.SelectedRevision"
ng-options="revision as revision.revision for revision in ctrl.application.Revisions"></select>
</div>
<div class="col-sm-2">
<button class="btn btn-primary btn-sm" style="margin-left: 0px;" type="button" ng-click="ctrl.rollbackApplication()"
ng-disabled="ctrl.formValues.SelectedRevision.revision === ctrl.application.CurrentRevision.revision">Rollback</button>
</div>
</div>
</form>
</td>
</tr> -->
</tbody>
</table>
</div>
</uib-tab>
<uib-tab index="1" classes="btn-sm" select="ctrl.selectTab(1)">
<uib-tab-heading>
<i class="fas fa-compress-arrows-alt space-right" aria-hidden="true"></i> Placement
<div ng-if="ctrl.state.placementWarning">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
warning
</div>
</uib-tab-heading>
<div class="small text-muted" style="padding: 20px;">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
The placement component helps you understand whether or not this application can be deployed on a specific node.
</div>
<kubernetes-application-placements-datatable
title-text="Placement constraints/preferences"
title-icon="fa-compress-arrows-alt"
dataset="ctrl.placements"
table-key="kubernetes.application.placements"
order-by="Name"
reverse-order="false"
loading="ctrl.state.dataLoading"
refresh-callback="ctrl.getApplication"
></kubernetes-application-placements-datatable>
</uib-tab>
<uib-tab index="2" classes="btn-sm" select="ctrl.selectTab(2)">
<uib-tab-heading>
<i class="fa fa-history space-right" aria-hidden="true"></i> Events
<div ng-if="ctrl.hasEventWarnings()">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
{{ ctrl.state.eventWarningCount }} warning(s)
</div>
</uib-tab-heading>
<kubernetes-events-datatable
title-text="Events"
title-icon="fa-history"
dataset="ctrl.events"
table-key="kubernetes.application.events"
order-by="Date"
reverse-order="true"
loading="ctrl.state.eventsLoading"
refresh-callback="ctrl.getEvents"
></kubernetes-events-datatable>
</uib-tab>
<uib-tab index="3" ng-if="ctrl.application.Yaml" select="ctrl.showEditor()" classes="btn-sm">
<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="application-yaml" data="ctrl.application.Yaml"></kubernetes-yaml-inspector>
</div>
</uib-tab>
</uib-tabset>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-body>
<div ng-if="!ctrl.isSystemNamespace()" style="margin-bottom: 15px;">
<button ng-if="!ctrl.isExternalApplication()" type="button" class="btn btn-sm btn-primary" ui-sref="kubernetes.applications.application.edit" style="margin-left: 0;">
<i class="fa fa-file-code space-right" aria-hidden="true"></i>Edit this application
</button>
<button
ng-if="ctrl.application.ApplicationType !== ctrl.KubernetesApplicationTypes.POD"
type="button"
class="btn btn-sm btn-primary"
style="margin-left: 0;"
ng-click="ctrl.redeployApplication()"
>
<i class="fa fa-redo space-right" aria-hidden="true"></i>Redeploy
</button>
<button
ng-if="!ctrl.isExternalApplication()"
type="button"
class="btn btn-sm btn-primary"
style="margin-left: 0;"
ng-click="ctrl.rollbackApplication()"
ng-disabled="ctrl.application.Revisions.length < 2 || ctrl.state.appType !== ctrl.KubernetesDeploymentTypes.APPLICATION_FORM"
>
<i class="fas fa-history space-right" aria-hidden="true"></i>Rollback to previous configuration
</button>
<a
ng-if="ctrl.isStack() && ctrl.stackFileContent"
class="btn btn-sm btn-primary space-left"
ui-sref="kubernetes.templates.custom.new({fileContent: ctrl.stackFileContent})"
>
<i class="fas fa-plus space-right" aria-hidden="true"></i>Create template from application
</a>
</div>
<!-- ACCESSING APPLICATION -->
<div class="text-muted" style="margin-bottom: 15px;">
<i class="fa fa-external-link-alt" aria-hidden="true" style="margin-right: 2px;"></i> Accessing the application
</div>
<div class="small text-muted" ng-if="ctrl.application.PublishedPorts.length === 0" style="margin-bottom: 15px;">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application is not exposing any port.
</div>
<div ng-if="ctrl.application.PublishedPorts.length > 0">
<!-- LB notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.LOAD_BALANCER">
<div class="small text-muted">
<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.
</div>
<div style="margin-top: 10px;" class="small text-muted">
<span ng-if="!ctrl.application.LoadBalancerIPAddress">
<p> Load balancer status: <i class="fa fa-cog fa-spin" style="margin-left: 2px;"></i> pending </p>
<p>
<u>what does the "pending" status means?</u>
<portainer-tooltip
position="bottom"
message="A pending status means that Portainer delegated the request to the provider responsible for creating the external load balancer. If it stays in pending state for long, this means that this capability might not be supported or you might have an issue with your cluster provider. Contact your cluster administrator for more information."
>
</portainer-tooltip>
</p>
</span>
<span ng-if="ctrl.application.LoadBalancerIPAddress">
<p> Load balancer status: <i class="fa fa-check green-icon" style="margin-left: 2px;"></i> available </p>
<p>
Load balancer IP address: {{ ctrl.application.LoadBalancerIPAddress }}
<span class="btn btn-primary btn-xs" ng-click="ctrl.copyLoadBalancerIP()" style="margin-left: 5px;">
<i class="fa fa-copy space-right" aria-hidden="true"></i>Copy
</span>
<span id="copyNotificationLB" style="margin-left: 7px; display: none; color: #23ae89;" class="small">
<i class="fa fa-check" aria-hidden="true"></i> copied
</span>
</p>
</span>
</div>
</div>
<!-- cluster notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.NODE_PORT">
<div class="small text-muted">
<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
below.
</div>
</div>
<!-- internal notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.CLUSTER_IP && !ctrl.state.useIngress">
<div class="small text-muted">
<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>
<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"
><i class="fa fa-check" aria-hidden="true"></i> copied</span
>
</div>
<div class="small text-muted" style="margin-top: 2px;">
<p>Refer to the below port configuration to access the application.</p>
</div>
</div>
<!-- ingress notice -->
<div ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.CLUSTER_IP && ctrl.state.useIngress">
<div class="small text-muted">
<p>
<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>
<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"
><i class="fa fa-check" aria-hidden="true"></i> copied</span
>
</p>
<p>It can also 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>
<!-- table -->
<div style="margin-top: 15px;">
<table class="table">
<tbody>
<tr class="text-muted">
<td style="width: 25%;">Container port</td>
<td style="width: 25%;">{{ ctrl.application.ServiceType | kubernetesApplicationPortsTableHeaderText }} port</td>
<td style="width: 50%;">HTTP route</td>
</tr>
<tr ng-repeat-start="port in ctrl.application.PublishedPorts">
<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" data-cy="k8sAppDetail-nodePort">
{{ port.NodePort }}
</span>
<span ng-if="ctrl.application.ServiceType !== ctrl.KubernetesServiceTypes.NODE_PORT">
{{ port.Port }}
</span>
<a
ng-if="ctrl.application.LoadBalancerIPAddress"
ng-href="http://{{ ctrl.application.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.portHasIngressRules(port)">-</td>
</tr>
<tr ng-repeat-end ng-repeat="rule in port.IngressRules">
<td>{{ port.TargetPort }}/{{ port.Protocol }}</td>
<td>
<span ng-if="ctrl.application.ServiceType === ctrl.KubernetesServiceTypes.NODE_PORT">
{{ port.NodePort }}
</span>
<span ng-if="ctrl.application.ServiceType !== ctrl.KubernetesServiceTypes.NODE_PORT">
{{ port.Port }}
</span>
<a
ng-if="ctrl.application.LoadBalancerIPAddress"
ng-href="http://{{ ctrl.application.LoadBalancerIPAddress }}:{{ port.Port }}"
target="_blank"
style="margin-left: 5px;"
>
<i class="fa fa-external-link-alt" aria-hidden="true"></i> access
</a>
</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>
</tbody>
</table>
</div>
</div>
<!-- !ACCESSING APPLICATION -->
<!-- AUTO SCALING -->
<div class="text-muted" style="margin-bottom: 15px;"> <i class="fa fa-expand-arrows-alt" aria-hidden="true" style="margin-right: 2px;"></i> Auto-scaling</div>
<div class="small text-muted" ng-if="!ctrl.application.AutoScaler" style="margin-bottom: 15px;">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application does not have an autoscaling policy defined.
</div>
<div ng-if="ctrl.application.AutoScaler">
<div style="margin-top: 15px; width: 50%;">
<table class="table">
<tbody>
<tr class="text-muted">
<td style="width: 33%;">Minimum instances</td>
<td style="width: 33%;">Maximum instances</td>
<td style="width: 33%;">
Target CPU usage
<portainer-tooltip position="bottom" message="The autoscaler will ensure enough instances are running to maintain an average CPU usage across all instances.">
</portainer-tooltip>
</td>
</tr>
<tr>
<td>{{ ctrl.application.AutoScaler.MinReplicas }}</td>
<td>{{ ctrl.application.AutoScaler.MaxReplicas }}</td>
<td>{{ ctrl.application.AutoScaler.TargetCPUUtilization }}%</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- !AUTO SCALING -->
<!-- CONFIGURATIONS -->
<div class="text-muted" style="margin-bottom: 15px; margin-top: 25px;"> <i class="fa fa-file-code" aria-hidden="true" style="margin-right: 2px;"></i> Configuration </div>
<div class="small text-muted" ng-if="!ctrl.application.Env.length > 0 && !ctrl.hasVolumeConfiguration()" style="margin-bottom: 15px;">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application is not using any environment variable or configuration.
</div>
<table class="table" ng-if="ctrl.application.Env.length > 0">
<tr class="text-muted">
<td style="width: 25%;">Container</td>
<td style="width: 25%;">Environment variable</td>
<td style="width: 25%;">Value</td>
<td style="width: 25%;">Configuration</td>
</tr>
<tbody ng-repeat="container in ctrl.application.Containers" style="border-top: 0;">
<tr ng-repeat="envvar in container.Env | orderBy: 'name'">
<td>
{{ container.Name }}
<span ng-if="container.Type === ctrl.KubernetesPodContainerTypes.INIT"
><i class="fa fa-asterisk" aria-hidden="true"></i> {{ envvar.valueFrom.fieldRef.fieldPath }} (<a
href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/"
target="_blank"
>init container</a
>)</span
>
</td>
<td>{{ envvar.name }}</td>
<td>
<span ng-if="envvar.value">{{ envvar.value }}</span>
<span ng-if="envvar.valueFrom.configMapKeyRef"><i class="fa fa-key" aria-hidden="true"></i> {{ envvar.valueFrom.configMapKeyRef.key }}</span>
<span ng-if="envvar.valueFrom.secretKeyRef"><i class="fa fa-key" aria-hidden="true"></i> {{ envvar.valueFrom.secretKeyRef.key }}</span>
<span ng-if="envvar.valueFrom.fieldRef"
><i class="fa fa-asterisk" aria-hidden="true"></i> {{ envvar.valueFrom.fieldRef.fieldPath }} (<a
href="https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/#capabilities-of-the-downward-api"
target="_blank"
>downward API</a
>)</span
>
<span ng-if="!envvar.value && !envvar.valueFrom.secretKeyRef && !envvar.valueFrom.configMapKeyRef && !envvar.valueFrom.fieldRef">-</span>
</td>
<td>
<span ng-if="envvar.value || envvar.valueFrom.fieldRef || (!envvar.valueFrom.secretKeyRef && !envvar.valueFrom.configMapKeyRef)">-</span>
<span ng-if="envvar.valueFrom.configMapKeyRef"
><a ui-sref="kubernetes.configurations.configuration({ name: envvar.valueFrom.configMapKeyRef.name, namespace: ctrl.application.ResourcePool })"
><i class="fa fa-file-code" aria-hidden="true"></i> {{ envvar.valueFrom.configMapKeyRef.name }}</a
></span
>
<span ng-if="envvar.valueFrom.secretKeyRef"
><a ui-sref="kubernetes.configurations.configuration({ name: envvar.valueFrom.secretKeyRef.name, namespace: ctrl.application.ResourcePool })"
><i class="fa fa-file-code" aria-hidden="true"></i> {{ envvar.valueFrom.secretKeyRef.name }}</a
></span
>
</td>
</tr>
</tbody>
</table>
<table class="table" ng-if="ctrl.hasVolumeConfiguration()">
<tr class="text-muted">
<td style="width: 25%;">Container</td>
<td style="width: 25%;">Configuration path</td>
<td style="width: 25%;">Value</td>
<td style="width: 25%;">Configuration</td>
</tr>
<tbody ng-repeat="container in ctrl.application.Containers" style="border-top: 0;">
<tr ng-repeat="volume in container.ConfigurationVolumes track by $index" style="border-top: 0;">
<td>
{{ container.Name }}
<span ng-if="container.Type === ctrl.KubernetesPodContainerTypes.INIT"
><i class="fa fa-asterisk" aria-hidden="true"></i> {{ envvar.valueFrom.fieldRef.fieldPath }} (<a
href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/"
target="_blank"
>init container</a
>)</span
>
</td>
<td>
{{ volume.fileMountPath }}
</td>
<td> <i class="fa fa-key" ng-if="volume.configurationKey" aria-hidden="true"></i> {{ volume.configurationKey ? volume.configurationKey : '-' }} </td>
<td>
<a ui-sref="kubernetes.configurations.configuration({ name: volume.configurationName, namespace: ctrl.application.ResourcePool })"
><i class="fa fa-file-code" aria-hidden="true"></i> {{ volume.configurationName }}</a
>
</td>
</tr>
</tbody>
</table>
<!-- !CONFIGURATIONS -->
<!-- DATA PERSISTENCE -->
<div class="text-muted" style="margin-bottom: 15px; margin-top: 25px;">
<i class="fa fa-database" aria-hidden="true" style="margin-right: 2px;"></i> Data persistence
</div>
<div class="small text-muted" ng-if="!ctrl.hasPersistedFolders()">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
This application has no persisted folders.
</div>
<div ng-if="ctrl.hasPersistedFolders()">
<div class="small text-muted" style="margin-bottom: 15px;">
Data access policy: <i class="fa {{ ctrl.application.DataAccessPolicy | kubernetesApplicationDataAccessPolicyIcon }}" aria-hidden="true"></i>
{{ ctrl.application.DataAccessPolicy | kubernetesApplicationDataAccessPolicyText }}
<portainer-tooltip position="right" message="{{ ctrl.application.DataAccessPolicy | kubernetesApplicationDataAccessPolicyTooltip }}"> </portainer-tooltip>
</div>
<table class="table" ng-if="ctrl.application.DataAccessPolicy === ctrl.ApplicationDataAccessPolicies.SHARED">
<tr class="text-muted">
<td style="width: 33%;">Persisted folder</td>
<td style="width: 66%;">Persistence</td>
</tr>
<tbody ng-repeat="container in ctrl.application.Containers" style="border-top: 0;">
<tr ng-repeat="volume in container.PersistedFolders track by $index">
<td>
{{ volume.MountPath }}
</td>
<td ng-if="volume.PersistentVolumeClaimName">
<a ui-sref="kubernetes.volumes.volume({ name: volume.PersistentVolumeClaimName, namespace: ctrl.application.ResourcePool })"
><i class="fa fa-database" aria-hidden="true"></i> {{ volume.PersistentVolumeClaimName }}</a
>
</td>
<td ng-if="volume.HostPath"> {{ volume.HostPath }} on host filesystem </td>
</tr>
</tbody>
</table>
<table class="table" ng-if="ctrl.application.DataAccessPolicy === ctrl.ApplicationDataAccessPolicies.ISOLATED">
<thead>
<tr class="text-muted">
<td style="width: 25%;">Container name</td>
<td style="width: 25%;">Pod name</td>
<td style="width: 25%;">Persisted folder</td>
<td style="width: 25%;">Persistence</td>
</tr>
</thead>
<tbody ng-repeat="container in ctrl.allContainers track by $index" style="border-top: none;">
<tr ng-repeat="volume in container.PersistedFolders track by $index">
<td>
{{ container.Name }}
<span ng-if="container.Type === ctrl.KubernetesPodContainerTypes.INIT"
><i class="fa fa-asterisk" aria-hidden="true"></i> {{ envvar.valueFrom.fieldRef.fieldPath }} (<a
href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/"
target="_blank"
>init container</a
>)</span
>
</td>
<td>{{ container.PodName }}</td>
<td>
{{ volume.MountPath }}
</td>
<td ng-if="volume.PersistentVolumeClaimName">
<a ui-sref="kubernetes.volumes.volume({ name: volume.PersistentVolumeClaimName + '-' + container.PodName, namespace: ctrl.application.ResourcePool })">
<i class="fa fa-database" aria-hidden="true"></i> {{ volume.PersistentVolumeClaimName + '-' + container.PodName }}</a
>
</td>
<td ng-if="volume.HostPath"> {{ volume.HostPath }} on host filesystem </td>
</tr>
</tbody>
</table>
<!-- !DATA PERSISTENCE -->
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<kubernetes-containers-datatable
title-text="Application containers"
title-icon="fa-server"
dataset="ctrl.allContainers"
table-key="kubernetes.application.containers"
is-pod="ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD"
order-by="{{ ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD ? 'Name' : 'PodName' }}"
use-server-metrics="ctrl.state.useServerMetrics"
>
</kubernetes-containers-datatable>
</div>
</div>
</div>