mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
fix(ui): kubernetes-consistent-styling EE-3820 (#7425)
This commit is contained in:
parent
b67f404d8d
commit
36c93c7f57
80 changed files with 713 additions and 548 deletions
|
@ -14,15 +14,15 @@
|
|||
title="'Edit application'"
|
||||
breadcrumbs="[
|
||||
{ label:'Namespaces', link:'kubernetes.resourcePools' },
|
||||
{
|
||||
{
|
||||
label:ctrl.application.ResourcePool,
|
||||
link: 'kubernetes.resourcePools.resourcePool',
|
||||
link: 'kubernetes.resourcePools.resourcePool',
|
||||
linkParams:{ id: ctrl.application.ResourcePool }
|
||||
},
|
||||
{ label:'Applications', link:'kubernetes.applications' },
|
||||
{
|
||||
{
|
||||
label:ctrl.application.Name,
|
||||
link: 'kubernetes.applications.application',
|
||||
link: 'kubernetes.applications.application',
|
||||
linkParams:{ name: ctrl.application.Name, namespace: ctrl.application.ResourcePool }
|
||||
},
|
||||
'Edit',
|
||||
|
@ -97,10 +97,12 @@
|
|||
>
|
||||
<editor-description>
|
||||
<span class="text-muted small" ng-show="ctrl.stack.IsComposeFormat">
|
||||
<p>
|
||||
<p class="vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
||||
Portainer uses <a href="https://kompose.io/" target="_blank">Kompose</a> to convert your Compose manifest to a Kubernetes compliant manifest. Be wary that not
|
||||
all the Compose format options are supported by Kompose at the moment.
|
||||
<span>
|
||||
Portainer uses <a href="https://kompose.io/" target="_blank">Kompose</a> to convert your Compose manifest to a Kubernetes compliant manifest. Be wary that
|
||||
not all the Compose format options are supported by Kompose at the moment.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
You can get more information about Compose file format in the
|
||||
|
@ -108,8 +110,8 @@
|
|||
</p>
|
||||
</span>
|
||||
<span class="text-muted small" ng-show="!ctrl.stack.IsComposeFormat">
|
||||
<p>
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
<p class="vertical-center">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
This feature allows you to deploy any kind of Kubernetes resource in this environment (Deployment, Secret, ConfigMap...).
|
||||
</p>
|
||||
<p>
|
||||
|
@ -124,7 +126,7 @@
|
|||
<div class="col-sm-12 form-section-title"> Application </div>
|
||||
<!-- #region NAME FIELD -->
|
||||
<div class="form-group">
|
||||
<label for="application_name" class="col-sm-3 col-lg-2 control-label text-left">Name</label>
|
||||
<label for="application_name" class="col-sm-3 col-lg-2 control-label text-left required">Name</label>
|
||||
<div class="col-sm-8">
|
||||
<input
|
||||
type="text"
|
||||
|
@ -142,17 +144,20 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-show="kubernetesApplicationCreationForm.application_name.$invalid || ctrl.state.alreadyExists">
|
||||
<div class="col-sm-12 small">
|
||||
<div ng-messages="kubernetesApplicationCreationForm.application_name.$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This field is required.</p>
|
||||
<p ng-message="pattern">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
|
||||
<div class="small">
|
||||
<div class="col-sm-3 col-lg-2"></div>
|
||||
<div class="col-sm-8" ng-messages="kubernetesApplicationCreationForm.application_name.$error">
|
||||
<p class="text-muted vertical-center" ng-message="required"
|
||||
><pr-icon class="vertical-center" icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This field is required.</p
|
||||
>
|
||||
<p class="text-muted vertical-center" ng-message="pattern">
|
||||
<pr-icon class="vertical-center" icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
|
||||
This field must consist of lower case alphanumeric characters or '-', contain at most 63 characters, start with an alphabetic character, and end with an
|
||||
alphanumeric character (e.g. 'my-name', or 'abc-123').
|
||||
</p>
|
||||
</div>
|
||||
<p ng-if="ctrl.state.alreadyExists">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
|
||||
<p class="text-muted vertical-center" ng-if="ctrl.state.alreadyExists">
|
||||
<pr-icon class="vertical-center" icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
|
||||
An application with the same name already exists inside the selected namespace.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -166,8 +171,8 @@
|
|||
model="ctrl.formValues.ImageModel"
|
||||
ng-if="ctrl.formValues.ResourcePool"
|
||||
auto-complete="false"
|
||||
label-class="col-sm-1"
|
||||
input-class="col-sm-11"
|
||||
label-class="col-sm-3 col-lg-2"
|
||||
input-class="col-sm-8"
|
||||
namespace="ctrl.formValues.ResourcePool.Namespace.Name"
|
||||
endpoint="ctrl.endpoint"
|
||||
is-admin="ctrl.isAdmin"
|
||||
|
@ -182,8 +187,8 @@
|
|||
<div class="col-sm-12 form-section-title"> Stack </div>
|
||||
<!-- #region STACK -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
Portainer can automatically bundle multiple applications inside a stack. Enter a name of a new stack or select an existing stack in the list. Leave empty to
|
||||
use the application name.
|
||||
</div>
|
||||
|
@ -209,8 +214,8 @@
|
|||
<div class="col-sm-12 form-section-title"> Environment </div>
|
||||
<!-- #region ENVIRONMENT VARIABLES -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Environment variables</label>
|
||||
<div class="col-sm-12 vertical-center pt-2.5">
|
||||
<label class="control-label text-left !pt-0">Environment variables</label>
|
||||
<span
|
||||
ng-if="ctrl.formValues.Containers.length <= 1"
|
||||
class="label label-default interactive vertical-center"
|
||||
|
@ -227,7 +232,7 @@
|
|||
<div style="margin-top: 2px">
|
||||
<div class="col-sm-4 input-group input-group-sm">
|
||||
<div class="input-group col-sm-12 input-group-sm" ng-class="{ striked: envVar.NeedsDeletion }">
|
||||
<span class="input-group-addon">name</span>
|
||||
<span class="input-group-addon required">name</span>
|
||||
<input
|
||||
type="text"
|
||||
name="environment_variable_name_{{ $index }}"
|
||||
|
@ -257,7 +262,12 @@
|
|||
</div>
|
||||
|
||||
<div class="col-sm-2 input-group input-group-sm" ng-if="ctrl.formValues.Containers.length <= 1">
|
||||
<button ng-if="!envVar.NeedsDeletion" class="btn btn-md btn-light btn-only-icon" type="button" ng-click="ctrl.removeEnvironmentVariable(envVar)">
|
||||
<button
|
||||
ng-if="!envVar.NeedsDeletion"
|
||||
class="btn btn-md btn-dangerlight btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.removeEnvironmentVariable(envVar)"
|
||||
>
|
||||
<pr-icon icon="'trash-2'" size="'md'" feather="true"></pr-icon>
|
||||
</button>
|
||||
<button
|
||||
|
@ -277,7 +287,7 @@
|
|||
ctrl.state.duplicates.environmentVariables.refs[$index] !== undefined
|
||||
"
|
||||
>
|
||||
<div class="col-sm-4 input-group input-group-sm">
|
||||
<div class="col-sm-8 input-group input-group-sm">
|
||||
<div
|
||||
class="small"
|
||||
style="margin-top: 5px"
|
||||
|
@ -287,19 +297,19 @@
|
|||
"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['environment_variable_name_' + $index].$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Environment variable name is required.</p>
|
||||
<p ng-message="pattern"
|
||||
<p ng-message="required" class="text-muted vertical-center"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true" class-="vertical-center"></pr-icon> Environment variable name is required.</p
|
||||
>
|
||||
<p ng-message="pattern" class="text-muted vertical-center"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This field must consist of alphabetic characters, digits, '_', '-',
|
||||
or '.', and must not start with a digit (e.g. 'my.env-name', or 'MY_ENV.NAME', or 'MyEnvName1'.</p
|
||||
>
|
||||
</ng-messages>
|
||||
<p ng-if="ctrl.state.duplicates.environmentVariables.refs[$index] !== undefined"
|
||||
<p class="text-muted vertical-center" ng-if="ctrl.state.duplicates.environmentVariables.refs[$index] !== undefined"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This environment variable is already defined.</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 input-group input-group-sm"></div>
|
||||
<div class="col-sm-2 input-group input-group-sm"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -309,8 +319,8 @@
|
|||
<div class="col-sm-12 form-section-title"> Configurations </div>
|
||||
<!-- #region CONFIGURATIONS -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Configurations</label>
|
||||
<div class="col-sm-12 vertical-center pt-2.5">
|
||||
<label class="control-label text-left !pt-0">Configurations</label>
|
||||
<span
|
||||
class="label label-default interactive vertical-center"
|
||||
style="margin-left: 10px"
|
||||
|
@ -321,8 +331,8 @@
|
|||
<pr-icon icon="'plus'" mode="'alt'" size="'sm'" feather="true"></pr-icon> add configuration
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-sm-12 small text-muted" style="margin-top: 15px" ng-if="ctrl.formValues.Configurations.length">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div class="col-sm-12 small text-muted vertical-center" style="margin-top: 15px" ng-if="ctrl.formValues.Configurations.length">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
Portainer will automatically expose all the keys of a configuration as environment variables. This behavior can be overridden to filesystem mounts for each
|
||||
key via the override button.
|
||||
</div>
|
||||
|
@ -341,9 +351,9 @@
|
|||
data-cy="k8sAppCreate-addConfigSelect_{{ $index }}"
|
||||
></select>
|
||||
</div>
|
||||
<div class="col-sm-3" style="margin-top: 2px">
|
||||
<div class="col-sm-3">
|
||||
<button
|
||||
class="btn btn-sm btn-light vertical-center"
|
||||
class="btn btn-md btn-light vertical-center !ml-0"
|
||||
type="button"
|
||||
ng-if="!config.Overriden"
|
||||
ng-click="ctrl.overrideConfiguration(index)"
|
||||
|
@ -353,7 +363,7 @@
|
|||
<pr-icon icon="'list'" size="'md'" feather="true"></pr-icon> Override
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-light vertical-center"
|
||||
class="btn btn-md btn-light vertical-center !ml-0"
|
||||
type="button"
|
||||
ng-if="config.Overriden"
|
||||
ng-click="ctrl.resetConfiguration(index)"
|
||||
|
@ -363,13 +373,13 @@
|
|||
<pr-icon icon="'rotate-cw'" size="'md'" feather="true"></pr-icon> Auto
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-dangerlight vertical-center"
|
||||
class="btn btn-md btn-dangerlight vertical-center btn-only-icon h-[34px]"
|
||||
type="button"
|
||||
ng-click="ctrl.removeConfiguration(index)"
|
||||
ng-if="ctrl.formValues.Containers.length <= 1"
|
||||
data-cy="k8sAppCreate-configRemoveButton"
|
||||
>
|
||||
<pr-icon icon="'trash-2'" size="'md'" feather="true"></pr-icon> Remove
|
||||
<pr-icon icon="'trash-2'" size="'md'" feather="true"></pr-icon>
|
||||
</button>
|
||||
</div>
|
||||
<!-- no-override -->
|
||||
|
@ -390,16 +400,16 @@
|
|||
<div ng-repeat="(keyIndex, overridenKey) in config.OverridenKeys" style="margin-top: 2px">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-lg-2 form-group !m-0"><span> </span></div>
|
||||
<div class="col-sm-3 form-group" style="margin-left: -11px">
|
||||
<div class="col-sm-3 form-group !mr-1" style="margin-left: -11px">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon">configuration key</span>
|
||||
<input type="text" class="form-control" ng-value="overridenKey.Key" disabled />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 form-group" ng-if="overridenKey.Type === ctrl.ApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM">
|
||||
<div class="col-sm-3 form-group !mr-1" ng-if="overridenKey.Type === ctrl.ApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon">path on disk</span>
|
||||
<span class="input-group-addon required">path on disk</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
|
@ -428,9 +438,11 @@
|
|||
"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['overriden_key_path_' + index + '_' + keyIndex].$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Path is required.</p>
|
||||
<p class="vertical-center" ng-message="required"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Path is required.</p
|
||||
>
|
||||
</ng-messages>
|
||||
<p ng-if="ctrl.state.duplicates.configurationPaths.refs[index + '_' + keyIndex] !== undefined"
|
||||
<p class="vertical-center" ng-if="ctrl.state.duplicates.configurationPaths.refs[index + '_' + keyIndex] !== undefined"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This path is already used.</p
|
||||
>
|
||||
</div>
|
||||
|
@ -459,17 +471,17 @@
|
|||
<div class="col-sm-12 form-section-title"> Persisting data </div>
|
||||
<!-- #region PERSISTED FOLDERS -->
|
||||
<div class="form-group" ng-if="!ctrl.storageClassAvailable()">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
No storage option is available to persist data, contact your administrator to enable a storage option.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="ctrl.storageClassAvailable()">
|
||||
<div class="col-sm-12" style="margin-top: 5px" ng-if="!ctrl.allQuotasExhaustedAndNoVolumesAvailable()">
|
||||
<label class="control-label text-left">Persisted folders</label>
|
||||
<div class="col-sm-12 vertical-center pt-2.5" style="margin-top: 5px" ng-if="!ctrl.allQuotasExhaustedAndNoVolumesAvailable()">
|
||||
<label class="control-label text-left !pt-0">Persisted folders</label>
|
||||
<span
|
||||
class="label label-default interactive"
|
||||
class="label label-default interactive vertical-center"
|
||||
style="margin-left: 10px"
|
||||
ng-click="ctrl.addPersistedFolder()"
|
||||
ng-if="ctrl.isAddPersistentFolderButtonShowed()"
|
||||
|
@ -480,7 +492,7 @@
|
|||
</div>
|
||||
|
||||
<div class="col-sm-12" style="margin-top: 5px" ng-if="ctrl.allQuotasExhaustedAndNoVolumesAvailable()">
|
||||
<span class="small text-muted">
|
||||
<span class="small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
||||
This namespace has exhausted its storage capacity. Contact your administrator to expand the capacity of the namespace.
|
||||
</span>
|
||||
|
@ -489,7 +501,7 @@
|
|||
<div class="col-sm-12 form-inline" style="margin-top: 10px" ng-repeat="persistedFolder in ctrl.formValues.PersistedFolders">
|
||||
<div style="margin-top: 2px">
|
||||
<div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: persistedFolder.NeedsDeletion }">
|
||||
<span class="input-group-addon">path in container</span>
|
||||
<span class="input-group-addon required">path in container</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
|
@ -514,7 +526,7 @@
|
|||
"
|
||||
>
|
||||
<label
|
||||
class="btn btn-primary"
|
||||
class="btn btn-light"
|
||||
ng-model="persistedFolder.UseNewVolume"
|
||||
uib-btn-radio="true"
|
||||
ng-change="ctrl.useNewVolume($index)"
|
||||
|
@ -522,7 +534,7 @@
|
|||
>New volume</label
|
||||
>
|
||||
<label
|
||||
class="btn btn-primary"
|
||||
class="btn btn-light"
|
||||
ng-model="persistedFolder.UseNewVolume"
|
||||
uib-btn-radio="false"
|
||||
ng-change="ctrl.useExistingVolume($index)"
|
||||
|
@ -533,22 +545,23 @@
|
|||
</div>
|
||||
|
||||
<div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: persistedFolder.NeedsDeletion }" ng-if="persistedFolder.UseNewVolume">
|
||||
<span class="input-group-addon">requested size</span>
|
||||
<span class="input-group-addon required">requested size</span>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
class="form-control !rounded-none"
|
||||
name="persisted_folder_size_{{ $index }}"
|
||||
ng-model="persistedFolder.Size"
|
||||
placeholder="20"
|
||||
ng-min="0"
|
||||
min="0"
|
||||
required
|
||||
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
|
||||
ng-change="ctrl.onChangeVolumeRequestedSize()"
|
||||
/>
|
||||
<span class="input-group-addon" style="padding: 0">
|
||||
<span class="input-group-addon !p-0 !rounded-r-[5px]">
|
||||
<select
|
||||
class="form-control w-12 !h-[28px] !border-none !rounded-r-[5px] text-xs"
|
||||
ng-model="persistedFolder.SizeUnit"
|
||||
ng-style="{ width: '100%', height: '100%', cursor: ctrl.isEditAndExistingPersistedFolder($index) ? 'not-allowed' : 'auto' }"
|
||||
ng-style="{ height: '100%', cursor: ctrl.isEditAndExistingPersistedFolder($index) ? 'not-allowed' : 'auto' }"
|
||||
ng-options="unit for unit in ctrl.state.availableSizeUnits"
|
||||
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
|
||||
ng-change="ctrl.onChangeVolumeRequestedSize()"
|
||||
|
@ -595,12 +608,12 @@
|
|||
<div ng-if="!ctrl.isEditAndStatefulSet() && !ctrl.state.useExistingVolume[$index] && ctrl.formValues.Containers.length <= 1">
|
||||
<button
|
||||
ng-if="!persistedFolder.NeedsDeletion"
|
||||
class="btn btn-sm btn-danger"
|
||||
class="btn btn-sm btn-dangerlight !ml-0 h-[30px]"
|
||||
type="button"
|
||||
ng-click="ctrl.removePersistedFolder($index)"
|
||||
data-cy="k8sAppCreate-rmPersistentFolderButton"
|
||||
>
|
||||
<pr-icon icon="'trash-2'" feather="true"></pr-icon>
|
||||
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
|
||||
</button>
|
||||
<button
|
||||
ng-if="persistedFolder.NeedsDeletion"
|
||||
|
@ -616,6 +629,7 @@
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="flex flex-row gap-x-1"
|
||||
ng-show="
|
||||
kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$invalid ||
|
||||
ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined ||
|
||||
|
@ -627,36 +641,36 @@
|
|||
>
|
||||
<div class="input-group col-sm-3 input-group-sm">
|
||||
<div
|
||||
class="small text-warning"
|
||||
class="small text-muted"
|
||||
style="margin-top: 5px"
|
||||
ng-show="
|
||||
kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$invalid || ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined
|
||||
"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Path is required.</p>
|
||||
<p class="vertical-center" ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Path is required.</p>
|
||||
</ng-messages>
|
||||
<p ng-if="ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined"
|
||||
<p class="vertical-center" ng-if="ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This path is already defined.</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-2 input-group-sm"></div>
|
||||
|
||||
<div class="input-group col-sm-5 input-group-sm">
|
||||
<div class="input-group col-sm-offset-2 col-sm-3 input-group-sm">
|
||||
<div
|
||||
class="small text-warning"
|
||||
class="small text-muted"
|
||||
style="margin-top: 5px"
|
||||
ng-show="
|
||||
kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$invalid || ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined
|
||||
"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Size is required.</p>
|
||||
<p ng-message="min"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This value must be greater than zero.</p>
|
||||
<p class="vertical-center" ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Size is required.</p>
|
||||
<p class="vertical-center" ng-message="min"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This value must be greater than zero.</p
|
||||
>
|
||||
</ng-messages>
|
||||
<p ng-if="ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined">
|
||||
<p class="vertical-center" ng-if="ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
|
||||
You can only request up to
|
||||
{{ ctrl.state.storages.availabilities[persistedFolder.StorageClass.Name] | kubernetesAppStorageRequestSizeHumanReadable }} for
|
||||
|
@ -696,7 +710,7 @@
|
|||
|
||||
<!-- access policy options -->
|
||||
<div class="form-group" style="margin-bottom: 0">
|
||||
<div class="boxselector_wrapper">
|
||||
<div class="boxselector_wrapper !px-[15px]">
|
||||
<div
|
||||
ng-if="
|
||||
(!ctrl.state.isEdit && !ctrl.state.persistedFoldersUseExistingVolumes) ||
|
||||
|
@ -712,7 +726,7 @@
|
|||
/>
|
||||
<label for="data_access_isolated">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'box'" feather="true"></pr-icon>
|
||||
<pr-icon icon="'svg-cubes'"></pr-icon>
|
||||
Isolated
|
||||
</div>
|
||||
<p>Application will be deployed as a StatefulSet with each instantiating their own data</p>
|
||||
|
@ -734,7 +748,7 @@
|
|||
style="cursor: pointer; border-color: #767676"
|
||||
>
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'box'" feather="true"></pr-icon>
|
||||
<pr-icon icon="'svg-cubes'"></pr-icon>
|
||||
Isolated
|
||||
</div>
|
||||
<p>Application will be deployed as a StatefulSet with each instantiating their own data</p>
|
||||
|
@ -750,7 +764,7 @@
|
|||
/>
|
||||
<label for="data_access_shared">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'sliders'" feather="true"></pr-icon>
|
||||
<pr-icon icon="'box'" feather="true"></pr-icon>
|
||||
Shared
|
||||
</div>
|
||||
<p>Application will be deployed as a Deployment with a shared storage access</p>
|
||||
|
@ -782,22 +796,22 @@
|
|||
<div class="col-sm-12 form-section-title"> Resource reservations </div>
|
||||
<!-- #region RESOURCE RESERVATIONS -->
|
||||
<div class="form-group" ng-if="!ctrl.state.resourcePoolHasQuota">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
Resource reservations are applied per instance of the application.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="ctrl.state.resourcePoolHasQuota && !ctrl.resourceQuotaCapacityExceeded()">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
A resource quota is set on this namespace, you must specify resource reservations. Resource reservations are applied per instance of the application. Maximums
|
||||
are inherited from the namespace quota.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="ctrl.state.resourcePoolHasQuota && ctrl.resourceQuotaCapacityExceeded()">
|
||||
<div class="col-sm-12 small text-danger">
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'danger'" feather="true"></pr-icon>
|
||||
This namespace has exhausted its resource capacity and you will not be able to deploy the application. Contact your administrator to expand the capacity of
|
||||
the namespace.
|
||||
|
@ -806,22 +820,22 @@
|
|||
|
||||
<!-- memory-limit-input -->
|
||||
<div
|
||||
class="form-group"
|
||||
class="form-group flex"
|
||||
ng-if="
|
||||
(!ctrl.state.resourcePoolHasQuota || (ctrl.state.resourcePoolHasQuota && !ctrl.resourceQuotaCapacityExceeded())) && ctrl.formValues.Containers.length <= 1
|
||||
"
|
||||
>
|
||||
<label for="memory-limit" class="col-sm-3 col-lg-2 control-label text-left" style="margin-top: 20px">
|
||||
Memory
|
||||
<label for="memory-limit" class="col-sm-3 col-lg-2 control-label text-left flex flex-row items-center">
|
||||
Memory limit (MB)
|
||||
<portainer-tooltip
|
||||
message="'An instance of this application will reserve this amount of memory. If the instance memory usage exceeds the reservation, it might be subject to OOM.'"
|
||||
>
|
||||
</portainer-tooltip>
|
||||
</label>
|
||||
<div class="col-sm-3">
|
||||
<div class="col-sm-6">
|
||||
<slider model="ctrl.formValues.MemoryLimit" floor="ctrl.state.sliders.memory.min" ceil="ctrl.state.sliders.memory.max" step="128"></slider>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<div class="col-sm-2 vertical-center">
|
||||
<input
|
||||
name="memory_limit"
|
||||
ng-model="ctrl.formValues.MemoryLimit"
|
||||
|
@ -834,14 +848,12 @@
|
|||
data-cy="k8sAppCreate-memoryLimit"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<p class="small text-muted" style="margin-top: 7px"> Maximum memory usage (<b>MB</b>) </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-show="kubernetesApplicationCreationForm.memory_limit.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div class="col-sm-3 col-lg-2"></div>
|
||||
<div class="col-sm-8 small text-muted">
|
||||
<div ng-messages="kubernetesApplicationCreationForm.memory_limit.$error">
|
||||
<p
|
||||
<p class="vertical-center"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Value must be between {{ ctrl.state.sliders.memory.min }} and
|
||||
{{ ctrl.state.sliders.memory.max }}
|
||||
</p>
|
||||
|
@ -851,28 +863,26 @@
|
|||
<!-- !memory-limit-input -->
|
||||
<!-- cpu-limit-input -->
|
||||
<div
|
||||
class="form-group"
|
||||
class="form-group flex"
|
||||
ng-if="
|
||||
(!ctrl.state.resourcePoolHasQuota || (ctrl.state.resourcePoolHasQuota && !ctrl.resourceQuotaCapacityExceeded())) && ctrl.formValues.Containers.length <= 1
|
||||
"
|
||||
>
|
||||
<label for="cpu-limit" class="col-sm-3 col-lg-2 control-label text-left" style="margin-top: 20px">
|
||||
CPU
|
||||
<label for="cpu-limit" class="col-sm-3 col-lg-2 control-label text-left flex flex-row items-center">
|
||||
CPU limit
|
||||
<portainer-tooltip
|
||||
message="'An instance of this application will reserve this amount of CPU. If the instance CPU usage exceeds the reservation, it might be subject to CPU throttling.'"
|
||||
>
|
||||
</portainer-tooltip>
|
||||
</label>
|
||||
<div class="col-sm-5">
|
||||
<div class="col-sm-8">
|
||||
<slider model="ctrl.formValues.CpuLimit" floor="ctrl.state.sliders.cpu.min" ceil="ctrl.state.sliders.cpu.max" step="0.10" precision="2"></slider>
|
||||
</div>
|
||||
<div class="col-sm-4" style="margin-top: 20px">
|
||||
<p class="small text-muted"> Maximum CPU usage </p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="ctrl.nodeLimitsOverflow()">
|
||||
<div class="col-sm-12 small text-danger">
|
||||
<div class="col-sm-3 col-lg-2"></div>
|
||||
<div class="col-sm-8 small text-muted">
|
||||
<pr-icon icon="'alert-circle'" mode="'danger'" feather="true"></pr-icon>
|
||||
These reservations would exceed the resources currently available in the cluster.
|
||||
</div>
|
||||
|
@ -888,7 +898,7 @@
|
|||
|
||||
<!-- deployment options -->
|
||||
<div class="form-group" style="margin-bottom: 0">
|
||||
<div class="boxselector_wrapper">
|
||||
<div class="boxselector_wrapper !px-[15px]">
|
||||
<div>
|
||||
<input
|
||||
type="radio"
|
||||
|
@ -905,7 +915,7 @@
|
|||
<p>Run one or multiple instances of this container</p>
|
||||
</label>
|
||||
</div>
|
||||
<div style="color: #767676" ng-if="!ctrl.supportGlobalDeployment()">
|
||||
<div ng-if="!ctrl.supportGlobalDeployment()">
|
||||
<input type="radio" id="deployment_global" disabled />
|
||||
<label
|
||||
for="deployment_global"
|
||||
|
@ -913,10 +923,9 @@
|
|||
tooltip-placement="bottom"
|
||||
tooltip-class="portainer-tooltip"
|
||||
uib-tooltip="The storage or access policy used for persisted folders cannot be used with this option"
|
||||
style="cursor: pointer; border-color: #767676"
|
||||
>
|
||||
<div class="boxselector_header">
|
||||
<i class="fa fa-cubes" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
<pr-icon icon="'svg-cubes'"></pr-icon>
|
||||
Global
|
||||
</div>
|
||||
<p>Application will be deployed as a DaemonSet with an instance on each node of the cluster</p>
|
||||
|
@ -933,10 +942,10 @@
|
|||
/>
|
||||
<label for="deployment_global">
|
||||
<div class="boxselector_header">
|
||||
<i class="fa fa-cubes" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
<pr-icon icon="'svg-cubes'"></pr-icon>
|
||||
Global
|
||||
</div>
|
||||
<p>Application will be deployed as a DaemonSet with an instance on each node of the cluster</p>
|
||||
<p>Application will be deployed as a DaemonSet with an instance on each node of the sdfh</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -945,8 +954,8 @@
|
|||
|
||||
<!-- replica count -->
|
||||
<div class="form-group form-inline" ng-if="ctrl.formValues.DeploymentType === ctrl.ApplicationDeploymentTypes.REPLICATED">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left"> Instance count </label>
|
||||
<div class="col-sm-12 vertical-center">
|
||||
<label class="control-label text-left !pt-0"> Instance count </label>
|
||||
<input
|
||||
type="number"
|
||||
name="replica_count"
|
||||
|
@ -964,10 +973,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="kubernetesApplicationCreationForm['replica_count'].$invalid">
|
||||
<div class="col-sm-12 small">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<ng-messages for="kubernetesApplicationCreationForm['replica_count'].$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Instance count is required.</p>
|
||||
<p ng-message="min"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Instance count must be greater than 0.</p>
|
||||
<p class="vertical-center" ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Instance count is required.</p>
|
||||
<p class="vertical-center" ng-message="min"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Instance count must be greater than 0.</p
|
||||
>
|
||||
</ng-messages>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -977,33 +988,37 @@
|
|||
class="form-group"
|
||||
ng-if="!ctrl.resourceReservationsOverflow() && ctrl.formValues.ReplicaCount > 1 && (ctrl.formValues.CpuLimit !== 0 || ctrl.formValues.MemoryLimit !== 0)"
|
||||
>
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
This application will reserve the following resources:
|
||||
<b>{{ ctrl.formValues.CpuLimit * ctrl.formValues.ReplicaCount | kubernetesApplicationCPUValue }} CPU</b> and
|
||||
<b>{{ ctrl.formValues.MemoryLimit * ctrl.formValues.ReplicaCount }} MB</b> of memory.
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div>
|
||||
This application will reserve the following resources:
|
||||
<b>{{ ctrl.formValues.CpuLimit * ctrl.formValues.ReplicaCount | kubernetesApplicationCPUValue }} CPU</b> and
|
||||
<b>{{ ctrl.formValues.MemoryLimit * ctrl.formValues.ReplicaCount }} MB</b> of memory.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="ctrl.resourceReservationsOverflow()">
|
||||
<div class="col-sm-12 small">
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'danger'" feather="true"></pr-icon>
|
||||
This application would exceed available resources. Please review resource reservations or the instance count.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="ctrl.state.storages.quotaExceeded">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
||||
This application would exceed available storage. Please review the persisted folders or the instance count.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="!ctrl.supportScalableReplicaDeployment()">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
||||
The following storage option(s) do not support concurrent access from multiples instances: <code>{{ ctrl.getNonScalableStorage() }}</code
|
||||
>. You will not be able to scale that application.
|
||||
<div>
|
||||
The following storage option(s) do not support concurrent access from multiples instances: <code>{{ ctrl.getNonScalableStorage() }}</code
|
||||
>. You will not be able to scale that application.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- #endregion -->
|
||||
|
@ -1013,8 +1028,10 @@
|
|||
|
||||
<div class="form-group" ng-if="ctrl.formValues.DeploymentType !== ctrl.ApplicationDeploymentTypes.GLOBAL && ctrl.state.useServerMetrics">
|
||||
<div class="col-sm-12">
|
||||
<label for="enable_auto_scaling" class="control-label text-left"> Enable auto scaling for this application </label>
|
||||
<label class="switch" style="margin-left: 20px">
|
||||
<div class="col-sm-3 col-lg-2 pl-0 pt-0">
|
||||
<label for="enable_auto_scaling" class="control-label text-left"> Enable auto scaling for this application </label>
|
||||
</div>
|
||||
<label class="switch ml-4 mt-1">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-control"
|
||||
|
@ -1022,7 +1039,7 @@
|
|||
ng-model="ctrl.formValues.AutoScaler.IsUsed"
|
||||
data-cy="k8sAppCreate-autoScaleCheckbox"
|
||||
/>
|
||||
<i></i>
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1137,23 +1154,23 @@
|
|||
|
||||
<!-- #region PLACEMENTS -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Placement rules</label>
|
||||
<div class="col-sm-12 vertical-center pt-2.5">
|
||||
<label class="control-label text-left !pt-0">Placement rules</label>
|
||||
<span class="label label-default interactive vertical-center" style="margin-left: 10px" ng-click="ctrl.addPlacement()">
|
||||
<pr-icon icon="'plus'" mode="'alt'" size="'sm'" feather="true"></pr-icon> add rule
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 small text-muted" ng-if="ctrl.formValues.Placements.length > 0" style="margin-top: 10px">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
|
||||
Deploy this application on nodes that respect <b>ALL</b> of the following placement rules. Placement rules are based on node labels.
|
||||
<div class="col-sm-12 small text-muted vertical-center" ng-if="ctrl.formValues.Placements.length > 0" style="margin-top: 10px">
|
||||
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
|
||||
<div> Deploy this application on nodes that respect <b>ALL</b> of the following placement rules. Placement rules are based on node labels. </div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 form-inline" style="margin-top: 10px">
|
||||
<div ng-repeat-start="placement in ctrl.formValues.Placements" style="margin-top: 2px">
|
||||
<div class="col-sm-5 input-group" ng-class="{ striked: placement.NeedsDeletion }">
|
||||
<select
|
||||
class="form-control"
|
||||
class="form-control !rounded"
|
||||
ng-model="placement.Label"
|
||||
ng-options="label as (label.Key | kubernetesNodeLabelHumanReadbleText) for label in ctrl.nodesLabels"
|
||||
ng-change="ctrl.onChangePlacementLabel($index)"
|
||||
|
@ -1164,7 +1181,7 @@
|
|||
</div>
|
||||
<div class="col-sm-5 input-group" ng-class="{ striked: placement.NeedsDeletion }">
|
||||
<select
|
||||
class="form-control"
|
||||
class="form-control !rounded"
|
||||
ng-model="placement.Value"
|
||||
ng-options="value for value in placement.Label.Values"
|
||||
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
|
||||
|
@ -1176,7 +1193,7 @@
|
|||
<div class="col-sm-1 input-group">
|
||||
<button
|
||||
ng-if="!placement.NeedsDeletion"
|
||||
class="btn btn-sm btn-light btn-only-icon"
|
||||
class="btn btn-md btn-dangerlight btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.removePlacement($index)"
|
||||
data-cy="k8sAppCreate-deletePlacementButton"
|
||||
|
@ -1185,7 +1202,7 @@
|
|||
</button>
|
||||
<button
|
||||
ng-if="placement.NeedsDeletion"
|
||||
class="btn btn-sm btn-light btn-only-icon"
|
||||
class="btn btn-sm btn-light btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.restorePlacement($index)"
|
||||
data-cy="k8sAppCreate-restorePlacementButton"
|
||||
|
@ -1196,8 +1213,8 @@
|
|||
</div>
|
||||
<div ng-repeat-end ng-show="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<div class="col-sm-5 input-group">
|
||||
<div class="small text-warning" style="margin-top: 5px" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<p ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<div class="small text-muted" style="margin-top: 5px" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<p class="vertical-center" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This label is already defined.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -1218,7 +1235,7 @@
|
|||
|
||||
<!-- placement policy options -->
|
||||
<div class="form-group" style="margin-bottom: 0" ng-if="ctrl.formValues.Placements.length">
|
||||
<div class="boxselector_wrapper">
|
||||
<div class="boxselector_wrapper !px-[15px]">
|
||||
<div>
|
||||
<input
|
||||
type="radio"
|
||||
|
@ -1316,7 +1333,7 @@
|
|||
<button
|
||||
ng-if="ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM"
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
class="btn btn-primary btn-sm !ml-0"
|
||||
ng-disabled="!kubernetesApplicationCreationForm.$valid || ctrl.isDeployUpdateButtonDisabled() || !ctrl.imageValidityIsValid()"
|
||||
ng-click="ctrl.deployApplication()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue