<page-header ng-if="ctrl.state.viewReady" title="'Node details'" breadcrumbs="[{ label:'Cluster', link:'kubernetes.cluster' }, ctrl.node.Name]" reload="true"></page-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 class="flex-center gap-1"> <pr-icon icon="'hard-drive'" size="'sm'"></pr-icon> Node </uib-tab-heading> <form class="form-horizontal" name="kubernetesNodeUpdateForm" style="padding: 20px" autocomplete="off"> <table class="table"> <tbody ng-if="ctrl.node"> <tr> <td>Hostname</td> <td> {{ ctrl.node.Name }} <span class="label label-primary image-tag" style="margin-left: 5px" ng-if="ctrl.node.Api">api</span> </td> </tr> <tr ng-if="ctrl.node.Api"> <td> Kubernetes API </td> <td>{{ ctrl.node.IPAddress }}:{{ ctrl.node.Port }}</td> </tr> <tr> <td>Role</td> <td>{{ ctrl.node.Role }}</td> </tr> <tr> <td>Kubelet version</td> <td>{{ ctrl.node.Version }}</td> </tr> <tr> <td>Creation date</td> <td>{{ ctrl.node.CreationDate | getisodate }}</td> </tr> <tr> <td>Status</td> <td> <span class="label label-{{ ctrl.node.Status | kubernetesNodeStatusColor }}"> {{ ctrl.node.Status }} </span> <span ng-if="ctrl.node.Status == 'Warning'" class="text text-warning"> {{ ctrl.node.Conditions | kubernetesNodeConditionsMessage }} </span> </td> </tr> <tr> <td class="col-xs-3"> Availability </td> <td class="col-xs-9"> <div class="flex flex-col"> <select class="form-control" name="availability" style="display: inline-block; width: 16rem" ng-model="ctrl.formValues.Availability"> <option>{{ ctrl.availabilities.ACTIVE }}</option> <option>{{ ctrl.availabilities.PAUSE }}</option> <option>{{ ctrl.availabilities.DRAIN }}</option> </select> <div class="small text-warning vertical-center" ng-if="ctrl.state.isDrainOperation && ctrl.formValues.Availability === ctrl.availabilities.DRAIN"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Cannot use this action while another node is currently being drained. </div> <div class="small text-warning vertical-center" ng-if="ctrl.state.isContainPortainer && ctrl.formValues.Availability === ctrl.availabilities.DRAIN"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Cannot drain a node where this Portainer instance is running. </div> </div> </td> </tr> </tbody> </table> <div style="padding: 8px"> <kubernetes-resource-reservation ng-if="ctrl.resourceReservation" cpu-reservation="ctrl.resourceReservation.CPU" cpu-usage="ctrl.resourceUsage.CPU" cpu-limit="ctrl.node.CPU" memory-reservation="ctrl.resourceReservation.Memory" memory-usage="ctrl.resourceUsage.Memory" memory-limit="ctrl.memoryLimit" description="Resource reservation represents the total amount of resource assigned to all the applications running on this node." display-usage="ctrl.hasResourceUsageAccess()" > </kubernetes-resource-reservation> </div> <div style="padding: 8px"> <!-- #region labels --> <div class="col-sm-12 form-section-title"> Labels </div> <div style="margin-bottom: 10px"> <span class="label label-default interactive vertical-center" ng-click="ctrl.addLabel()"> <pr-icon icon="'plus'"></pr-icon> add label </span> </div> <div class="form-inline py-1" ng-repeat="label in ctrl.formValues.Labels"> <div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: label.NeedsDeletion }"> <span class="input-group-addon">Key</span> <input type="text" class="form-control" name="label_key_{{ $index }}" ng-model="label.Key" ng-change="ctrl.onChangeLabelKey($index)" ng-disabled="ctrl.isSystemLabel($index)" required /> </div> <div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: label.NeedsDeletion }"> <span class="input-group-addon">Value</span> <input type="text" class="form-control" name="label_value_{{ $index }}" ng-change="ctrl.onChangeLabel($index)" ng-model="label.Value" ng-disabled="ctrl.isSystemLabel($index)" /> </div> <div class="input-group col-sm-1 input-group-sm"> <div style="white-space: nowrap"> <button ng-if="!ctrl.isSystemLabel($index) && !label.NeedsDeletion" class="btn btn-sm btn-dangerlight btn-only-icon" type="button" ng-click="ctrl.removeLabel($index)" > <pr-icon icon="'x'" mode="'error'" size="'sm'"></pr-icon> </button> <button ng-if="!ctrl.isSystemLabel($index) && label.NeedsDeletion" class="btn btn-sm btn-secondary" type="button" ng-click="ctrl.restoreLabel($index)"> Restore </button> <span class="label label-warning label-sm image-tag" ng-if="label.IsUsed && !ctrl.isSystemLabel($index)" style="margin-left: 5px">used</span> <span class="label label-info image-tag" ng-if="ctrl.isSystemLabel($index)" style="margin-left: 5px">system</span> </div> </div> <div class="small text-warning mt-2" ng-show="kubernetesNodeUpdateForm['label_key_' + $index].$invalid || ctrl.state.duplicateLabelKeys[$index] !== undefined"> <ng-messages for="kubernetesNodeUpdateForm['label_key_' + $index].$error"> <p ng-message="required" class="vertical-center"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Label key is required. </p> </ng-messages> <p ng-if="ctrl.state.duplicateLabelKeys[$index] !== undefined" class="vertical-center"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This label key is already defined. </p> </div> </div> <!-- #endregion --> <!-- #region taints --> <div class="col-sm-12 form-section-title" style="margin-top: 20px"> Taints </div> <div style="margin-bottom: 10px"> <span class="label label-default interactive vertical-center" ng-click="ctrl.addTaint()"> <pr-icon icon="'plus'"></pr-icon> add taint </span> </div> <div class="form-inline" ng-repeat="taint in ctrl.formValues.Taints" style="padding: 3px 0 3px 0"> <div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: taint.NeedsDeletion }"> <span class="input-group-addon">Key</span> <input type="text" class="form-control" name="taint_key_{{ $index }}" ng-model="taint.Key" ng-change="ctrl.onChangeTaintKey($index)" required /> </div> <div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: taint.NeedsDeletion }"> <span class="input-group-addon">Value</span> <input type="text" class="form-control" name="taint_value_{{ $index }}" ng-model="taint.Value" ng-change="ctrl.onChangeTaint($index)" /> </div> <div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: taint.NeedsDeletion }"> <span class="input-group-addon">Effect</span> <select id="taint_effect_{{ $index }}" name="taint_effect_{{ $index }}" class="form-control" ng-model="taint.Effect" ng-change="ctrl.onChangeTaint($index)" ; ng-options="effect as effect for effect in ctrl.availableEffects" ></select> </div> <div class="input-group col-sm-1 input-group-sm"> <div> <button ng-if="!taint.NeedsDeletion" class="btn btn-sm btn-dangerlight btn-only-icon" type="button" ng-click="ctrl.removeTaint($index)"> <pr-icon icon="'x'" mode="'error'" size="'sm'"></pr-icon> </button> <button ng-if="taint.NeedsDeletion" class="btn btn-sm btn-secondary" type="button" ng-click="ctrl.restoreTaint($index)"> Restore </button> </div> </div> <div class="small text-warning" style="margin-top: 5px" ng-show="kubernetesNodeUpdateForm['taint_key_' + $index].$invalid || ctrl.state.duplicateTaintKeys[$index] !== undefined" > <ng-messages for="kubernetesNodeUpdateForm['taint_key_' + $index].$error"> <p ng-message="required" class="vertical-center"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Taint key is required. </p> </ng-messages> <p ng-if="ctrl.state.duplicateTaintKeys[$index] !== undefined"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This taint key is already defined. </p> </div> </div> <!-- #endregion --> <!-- #region actions --> <div class="col-sm-12 form-section-title" style="margin-top: 20px"> Actions </div> <div class="form-group"> <div class="col-sm-12"> <button class="btn btn-primary btn-sm" type="button" style="margin-left: 0" ng-click="ctrl.updateNode()" ng-disabled="kubernetesNodeUpdateForm.$invalid || !ctrl.isFormValid()" > Update node </button> <button class="btn btn-default btn-sm" type="button" ng-click="ctrl.resetFormValues()" ng-disabled="ctrl.isNoChangesMade()"> Cancel </button> </div> </div> <!-- #endregion --> </div> </form> </uib-tab> <uib-tab index="1" classes="btn-sm" select="ctrl.selectTab(1)"> <uib-tab-heading> <div class="flex-center gap-1"> <pr-icon icon="'history'" size="'sm'"></pr-icon> Events </div> <div class="flex-center gap-1" ng-if="ctrl.hasEventWarnings()"> <pr-icon icon="'alert-circle'" mode="'warning-alt'" size="'sm'"></pr-icon> {{ ctrl.state.eventWarningCount }} warning(s) </div> </uib-tab-heading> <kubernetes-events-datatable title-text="Events" dataset="ctrl.events" table-key="kubernetes.node.events" order-by="Date" reverse-order="true" loading="ctrl.state.eventsLoading" refresh-callback="ctrl.getEvents" > </kubernetes-events-datatable> </uib-tab> <uib-tab index="2" ng-if="ctrl.node.Yaml" select="ctrl.showEditor()" classes="btn-sm"> <uib-tab-heading class="vertical-center"> <div class="flex-center gap-1"> <pr-icon icon="'code'" size="'sm'"></pr-icon> YAML </div> </uib-tab-heading> <div style="padding-right: 25px" ng-if="ctrl.state.showEditorTab"> <kubernetes-yaml-inspector key="node-yaml" data="ctrl.node.Yaml"> </kubernetes-yaml-inspector> </div> </uib-tab> </uib-tabset> </rd-widget-body> </rd-widget> </div> </div> <div class="row" ng-if="ctrl.applications && ctrl.applications.length > 0"> <div class="col-sm-12"> <kubernetes-node-applications-datatable dataset="ctrl.applications" table-key="kubernetes.node.applications" order-by="Name" refresh-callback="ctrl.getApplications" loading="ctrl.state.applicationsLoading" title-text="Applications running on this node" > </kubernetes-node-applications-datatable> </div> </div> </div>