2022-07-06 06:08:45 +00:00
< page-header
ng-if="!ctrl.state.isEdit"
title="'Create application'"
breadcrumbs="[
{ label:'Applications', link:'kubernetes.applications' },
'Create an application'
]"
reload="true"
>
< / page-header >
< page-header
ng-if="ctrl.state.isEdit"
title="'Edit application'"
breadcrumbs="[
{ label:'Namespaces', link:'kubernetes.resourcePools' },
2022-08-12 18:22:45 +00:00
{
2022-07-06 06:08:45 +00:00
label:ctrl.application.ResourcePool,
2022-08-12 18:22:45 +00:00
link: 'kubernetes.resourcePools.resourcePool',
2022-07-06 06:08:45 +00:00
linkParams:{ id: ctrl.application.ResourcePool }
},
{ label:'Applications', link:'kubernetes.applications' },
2022-08-12 18:22:45 +00:00
{
2022-07-06 06:08:45 +00:00
label:ctrl.application.Name,
2022-08-12 18:22:45 +00:00
link: 'kubernetes.applications.application',
2022-07-06 06:08:45 +00:00
linkParams:{ name: ctrl.application.Name, namespace: ctrl.application.ResourcePool }
},
'Edit',
]"
reload="true"
>
< / page-header >
2020-07-05 23:21:03 +00:00
< kubernetes-view-loading view-ready = "ctrl.state.viewReady" > < / kubernetes-view-loading >
< div ng-if = "ctrl.state.viewReady" >
2022-07-11 02:05:23 +00:00
< div class = "row kubernetes-create" >
2020-07-05 23:21:03 +00:00
< div class = "col-xs-12" >
< rd-widget >
< rd-widget-body >
< form class = "form-horizontal" name = "kubernetesApplicationCreationForm" autocomplete = "off" >
2022-01-16 19:37:46 +00:00
< div ng-if = "!ctrl.isExternalApplication()" >
< git-form-info-panel
ng-if="ctrl.state.appType == ctrl.KubernetesDeploymentTypes.GIT"
class-name="text-muted"
url="ctrl.stack.GitConfig.URL"
config-file-path="ctrl.stack.GitConfig.ConfigFilePath"
additional-files="ctrl.stack.AdditionalFiles"
type="application"
>< / git-form-info-panel >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" ng-if = "ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM" > Namespace < / div >
2022-01-16 19:37:46 +00:00
<!-- #region NAMESPACE -->
< div class = "form-group" ng-if = "ctrl.formValues.ResourcePool" >
2022-07-11 02:05:23 +00:00
< label for = "resource-pool-selector" class = "col-sm-3 col-lg-2 control-label text-left" > Namespace< / label >
< div class = "col-sm-8" >
2022-01-16 19:37:46 +00:00
< select
2021-09-07 00:37:26 +00:00
class="form-control"
2022-01-16 19:37:46 +00:00
id="resource-pool-selector"
ng-model="ctrl.formValues.ResourcePool"
ng-options="resourcePool.Namespace.Name for resourcePool in ctrl.resourcePools"
ng-change="ctrl.onResourcePoolSelectionChange()"
2021-09-07 00:37:26 +00:00
ng-disabled="ctrl.state.isEdit"
2022-01-16 19:37:46 +00:00
data-cy="k8sAppCreate-nsSelect"
>< / select >
2021-09-07 00:37:26 +00:00
< / div >
< / div >
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.state.resourcePoolHasQuota && ctrl.resourceQuotaCapacityExceeded() && ctrl.formValues.ResourcePool" >
< div class = "col-sm-12 small text-danger" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-triangle'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
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.
< / div >
< / div >
< div class = "form-group" ng-if = "!ctrl.formValues.ResourcePool" >
2022-09-14 23:09:19 +00:00
< div class = "col-sm-12 small text-warning" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-triangle'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
You do not have access to any namespace. Contact your administrator to get access to a namespace.
2020-07-05 23:21:03 +00:00
< / div >
< / div >
2021-09-07 00:37:26 +00:00
<!-- #endregion -->
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
<!-- #region Git repository -->
< kubernetes-redeploy-app-git-form
ng-if="ctrl.state.appType === ctrl.KubernetesDeploymentTypes.GIT"
stack="ctrl.stack"
namespace="ctrl.formValues.ResourcePool.Namespace.Name"
>< / kubernetes-redeploy-app-git-form >
<!-- #endregion -->
2021-03-24 18:27:32 +00:00
2022-01-16 19:37:46 +00:00
<!-- #region web editor -->
< web-editor-form
ng-if="ctrl.state.appType === ctrl.KubernetesDeploymentTypes.CONTENT"
value="ctrl.stackFileContent"
yml="true"
identifier="kubernetes-deploy-editor"
placeholder="# Define or paste the content of your manifest file here"
on-change="(ctrl.onChangeFileContent)"
>
< editor-description >
< span class = "text-muted small" ng-show = "ctrl.stack.IsComposeFormat" >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'warning'" feather = "true" > < / pr-icon >
2022-08-12 18:22:45 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< / p >
< p >
You can get more information about Compose file format in the
< a href = "https://docs.docker.com/compose/compose-file/" target = "_blank" > official documentation< / a > .
< / p >
< / span >
< span class = "text-muted small" ng-show = "!ctrl.stack.IsComposeFormat" >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" >
< pr-icon icon = "'info'" mode = "'primary'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
This feature allows you to deploy any kind of Kubernetes resource in this environment (Deployment, Secret, ConfigMap...).
< / p >
< p >
You can get more information about Kubernetes file format in the
< a href = "https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/" target = "_blank" > official documentation< / a > .
< / p >
< / span >
< / editor-description >
< / web-editor-form >
<!-- #endregion -->
< div ng-if = "ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Application < / div >
2022-01-16 19:37:46 +00:00
<!-- #region NAME FIELD -->
2021-09-22 04:01:28 +00:00
< div class = "form-group" >
2022-08-12 18:22:45 +00:00
< label for = "application_name" class = "col-sm-3 col-lg-2 control-label text-left required" > Name< / label >
2022-07-11 02:05:23 +00:00
< div class = "col-sm-8" >
2021-09-22 04:01:28 +00:00
< input
type="text"
class="form-control"
2022-01-16 19:37:46 +00:00
name="application_name"
ng-model="ctrl.formValues.Name"
ng-change="ctrl.onChangeName()"
placeholder="my-app"
2022-02-28 05:15:49 +00:00
ng-pattern="/^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$/"
2022-01-16 19:37:46 +00:00
auto-focus
required
ng-disabled="ctrl.state.isEdit"
data-cy="k8sAppCreate-applicationName"
2021-09-22 04:01:28 +00:00
/>
< / div >
2021-09-07 00:37:26 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-show = "kubernetesApplicationCreationForm.application_name.$invalid || ctrl.state.alreadyExists" >
2022-08-12 18:22:45 +00:00
< div class = "small" >
2022-08-22 20:54:40 +00:00
< div class = "col-sm-3 col-lg-2" > < / div >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-8" ng-messages = "kubernetesApplicationCreationForm.application_name.$error" >
2022-09-14 23:09:19 +00:00
< p class = "text-warning vertical-center" ng-message = "required"
2022-08-12 18:22:45 +00:00
>< pr-icon class = "vertical-center" icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > This field is required.< /p
>
2022-09-14 23:09:19 +00:00
< p class = "text-warning vertical-center" ng-message = "pattern" >
2022-08-12 18:22:45 +00:00
< pr-icon class = "vertical-center" icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon >
2022-02-28 05:15:49 +00:00
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 >
2022-01-16 19:37:46 +00:00
< / div >
2022-08-22 20:54:40 +00:00
< div class = "col-sm-8" ng-if = "ctrl.state.alreadyExists" >
2022-09-14 23:09:19 +00:00
< p class = "text-warning vertical-center" >
2022-08-22 20:54:40 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< / div >
< / div >
2021-09-22 04:01:28 +00:00
<!-- #endregion -->
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
<!-- #region IMAGE FIELD -->
2022-07-11 02:05:23 +00:00
< div class = "form-group mb-0" >
2021-09-22 04:01:28 +00:00
< div class = "col-sm-12" >
2022-01-16 19:37:46 +00:00
< por-image-registry
model="ctrl.formValues.ImageModel"
ng-if="ctrl.formValues.ResourcePool"
auto-complete="false"
2022-08-12 18:22:45 +00:00
label-class="col-sm-3 col-lg-2"
input-class="col-sm-8"
2022-01-16 19:37:46 +00:00
namespace="ctrl.formValues.ResourcePool.Namespace.Name"
endpoint="ctrl.endpoint"
is-admin="ctrl.isAdmin"
check-rate-limits="true"
set-validity="ctrl.setPullImageValidity"
>< / por-image-registry >
< / div >
< / div >
2022-07-11 02:05:23 +00:00
<!-- #end region IMAGE FIELD -->
2022-01-16 19:37:46 +00:00
< div ng-if = "ctrl.formValues.ResourcePool" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Stack < / div >
2022-01-16 19:37:46 +00:00
<!-- #region STACK -->
< div class = "form-group" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
< pr-icon icon = "'info'" mode = "'primary'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
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 >
2021-09-22 04:01:28 +00:00
< / div >
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
< div class = "form-group" >
2022-07-11 02:05:23 +00:00
< label for = "stack_name" class = "col-sm-3 col-lg-2 control-label text-left" > Stack< / label >
< div class = "col-sm-8" >
2022-01-16 19:37:46 +00:00
< input
type="text"
class="form-control"
placeholder="myStack"
ng-model="ctrl.formValues.StackName"
name="stack_name"
uib-typeahead="stack for stack in ctrl.stacks | filter:$viewValue | limitTo:7"
typeahead-min-length="0"
data-cy="k8sAppCreate-stackName"
/>
< / div >
< / div >
<!-- #endregion -->
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Environment < / div >
2022-01-16 19:37:46 +00:00
<!-- #region ENVIRONMENT VARIABLES -->
< div class = "form-group" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 vertical-center pt-2.5" >
< label class = "control-label text-left !pt-0" > Environment variables< / label >
2022-01-16 19:37:46 +00:00
< span
ng-if="ctrl.formValues.Containers.length < = 1"
2022-07-11 02:05:23 +00:00
class="label label-default interactive vertical-center"
2022-01-17 05:53:32 +00:00
style="margin-left: 10px"
2022-01-16 19:37:46 +00:00
ng-click="ctrl.addEnvironmentVariable()"
data-cy="k8sAppCreate-addEnvVarButton"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'plus'" mode = "'alt'" size = "'sm'" feather = "true" > < / pr-icon > add environment variable
2022-01-16 19:37:46 +00:00
< / span >
< / div >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-inline" style = "margin-top: 10px" >
< div ng-repeat = "envVar in ctrl.formValues.EnvironmentVariables | orderBy: 'NameIndex'" style = "margin-top: 2px" >
< div style = "margin-top: 2px" >
2022-01-16 19:37:46 +00:00
< 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 }" >
2022-08-12 18:22:45 +00:00
< span class = "input-group-addon required" > name< / span >
2022-01-16 19:37:46 +00:00
< input
type="text"
name="environment_variable_name_{{ $index }}"
class="form-control"
ng-model="envVar.Name"
ng-change="ctrl.onChangeEnvironmentName()"
ng-pattern="/^[-._a-zA-Z][-._a-zA-Z0-9]*$/"
placeholder="foo"
ng-disabled="ctrl.formValues.Containers.length > 1"
data-cy="k8sAppCreate-envVarName_{{ $index }}"
required
/>
< / div >
< / div >
< div class = "col-sm-4 input-group input-group-sm" ng-class = "{ striked: envVar.NeedsDeletion }" >
< span class = "input-group-addon" > value< / span >
2021-09-22 04:01:28 +00:00
< input
type="text"
2022-01-16 19:37:46 +00:00
name="environment_variable_value_{{ $index }}"
2021-09-22 04:01:28 +00:00
class="form-control"
2022-01-16 19:37:46 +00:00
ng-model="envVar.Value"
placeholder="bar"
2021-09-22 04:01:28 +00:00
ng-disabled="ctrl.formValues.Containers.length > 1"
2022-01-16 19:37:46 +00:00
data-cy="k8sAppCreate-envVarValue_{{ $index }}"
2021-09-22 04:01:28 +00:00
/>
< / div >
2022-01-16 19:37:46 +00:00
< div class = "col-sm-2 input-group input-group-sm" ng-if = "ctrl.formValues.Containers.length <= 1" >
2022-08-12 18:22:45 +00:00
< button
ng-if="!envVar.NeedsDeletion"
class="btn btn-md btn-dangerlight btn-only-icon !ml-0"
type="button"
ng-click="ctrl.removeEnvironmentVariable(envVar)"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'trash-2'" size = "'md'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< button
ng-if="envVar.NeedsDeletion"
2022-07-11 02:05:23 +00:00
class="btn btn-sm btn-light btn-only-icon"
2022-01-16 19:37:46 +00:00
type="button"
ng-click="ctrl.restoreEnvironmentVariable(envVar)"
data-cy="k8sAppCreate-removeEnvVarButton_{{ $index }}"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'rotate-cw'" size = "'md'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< / div >
2021-09-07 00:37:26 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div
ng-show="
kubernetesApplicationCreationForm['environment_variable_name_' + $index].$invalid ||
ctrl.state.duplicates.environmentVariables.refs[$index] !== undefined
"
>
2022-08-12 18:22:45 +00:00
< div class = "col-sm-8 input-group input-group-sm" >
2022-01-16 19:37:46 +00:00
< div
2022-07-11 02:05:23 +00:00
class="small"
2022-01-17 05:53:32 +00:00
style="margin-top: 5px"
2022-01-16 19:37:46 +00:00
ng-show="
kubernetesApplicationCreationForm['environment_variable_name_' + $index].$invalid ||
ctrl.state.duplicates.environmentVariables.refs[$index] !== undefined
"
>
< ng-messages for = "kubernetesApplicationCreationForm['environment_variable_name_' + $index].$error" >
2022-09-14 23:09:19 +00:00
< p ng-message = "required" class = "text-warning vertical-center"
2022-08-12 18:22:45 +00:00
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" class- = "vertical-center" > < / pr-icon > Environment variable name is required.< /p
>
2022-09-14 23:09:19 +00:00
< p ng-message = "pattern" class = "text-warning vertical-center"
2022-07-11 02:05:23 +00:00
>< 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
2022-01-16 19:37:46 +00:00
>
< / ng-messages >
2022-09-14 23:09:19 +00:00
< p class = "text-warning vertical-center" ng-if = "ctrl.state.duplicates.environmentVariables.refs[$index] !== undefined"
2022-07-11 02:05:23 +00:00
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > This environment variable is already defined.< /p
2022-01-16 19:37:46 +00:00
>
< / div >
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2021-02-26 15:50:33 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< / div >
< / div >
<!-- #endregion -->
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Configurations < / div >
2022-01-16 19:37:46 +00:00
<!-- #region CONFIGURATIONS -->
< div class = "form-group" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 vertical-center pt-2.5" >
< label class = "control-label text-left !pt-0" > Configurations< / label >
2022-01-16 19:37:46 +00:00
< span
2022-07-11 02:05:23 +00:00
class="label label-default interactive vertical-center"
2022-01-17 05:53:32 +00:00
style="margin-left: 10px"
2022-01-16 19:37:46 +00:00
ng-click="ctrl.addConfiguration()"
ng-if="ctrl.formValues.Containers.length < = 1"
data-cy="k8sAppCreate-addConfigButton"
2021-09-22 04:01:28 +00:00
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'plus'" mode = "'alt'" size = "'sm'" feather = "true" > < / pr-icon > add configuration
2022-01-16 19:37:46 +00:00
< / span >
< / div >
2022-08-12 18:22:45 +00:00
< 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 >
2022-06-13 06:53:51 +00:00
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.
2022-01-16 19:37:46 +00:00
< / div >
< / div >
<!-- config - element -->
< div class = "form-group" ng-repeat = "(index, config) in ctrl.formValues.Configurations" >
2022-07-11 02:05:23 +00:00
< label for = "stack_name" class = "col-sm-3 col-lg-2 control-label text-left" > Configuration< / label >
< div class = "col-sm-6" >
2022-01-16 19:37:46 +00:00
< select
class="form-control"
ng-model="config.SelectedConfiguration"
ng-options="c as c.Name for c in ctrl.configurations track by c.Name"
ng-change="ctrl.resetConfiguration(index)"
ng-disabled="ctrl.formValues.Containers.length > 1"
data-cy="k8sAppCreate-addConfigSelect_{{ $index }}"
>< / select >
< / div >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-3" >
2022-01-16 19:37:46 +00:00
< button
2022-08-12 18:22:45 +00:00
class="btn btn-md btn-light vertical-center !ml-0"
2022-01-16 19:37:46 +00:00
type="button"
ng-if="!config.Overriden"
ng-click="ctrl.overrideConfiguration(index)"
ng-disabled="!config.SelectedConfiguration || ctrl.formValues.Containers.length > 1"
data-cy="k8sAppCreate-configOverrideButton_{{ $index }}"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'list'" size = "'md'" feather = "true" > < / pr-icon > Override
2022-01-16 19:37:46 +00:00
< / button >
< button
2022-08-12 18:22:45 +00:00
class="btn btn-md btn-light vertical-center !ml-0"
2022-01-16 19:37:46 +00:00
type="button"
ng-if="config.Overriden"
ng-click="ctrl.resetConfiguration(index)"
ng-disabled="ctrl.formValues.Containers.length > 1"
data-cy="k8sAppCreate-configAutoButton_{{ $index }}"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'rotate-cw'" size = "'md'" feather = "true" > < / pr-icon > Auto
2022-01-16 19:37:46 +00:00
< / button >
< button
2022-08-12 18:22:45 +00:00
class="btn btn-md btn-dangerlight vertical-center btn-only-icon h-[34px]"
2022-01-16 19:37:46 +00:00
type="button"
ng-click="ctrl.removeConfiguration(index)"
ng-if="ctrl.formValues.Containers.length < = 1"
data-cy="k8sAppCreate-configRemoveButton"
>
2022-08-12 18:22:45 +00:00
< pr-icon icon = "'trash-2'" size = "'md'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< / div >
<!-- no - override -->
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12" style = "margin-top: 10px" ng-if = "config.SelectedConfiguration && !config.Overriden" >
2022-07-11 02:05:23 +00:00
< div class = "col-sm-3 col-lg-2" > < / div >
< div class = "col-sm-6 small text-muted" style = "padding-left: 5px" >
2022-01-16 19:37:46 +00:00
The following keys will be loaded from the < code > {{ config.SelectedConfiguration.Name }}< / code > configuration as environment variables:
< span ng-repeat = "(key, _) in config.SelectedConfiguration.Data" >
< code > {{ key }}< /code
>{{ $last ? '' : ', ' }}
< / span >
< / div >
< / div >
<!-- !no - override -->
<!-- has - override -->
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-inline" style = "margin-top: 10px" ng-if = "config.Overriden" >
< div ng-repeat = "(keyIndex, overridenKey) in config.OverridenKeys" style = "margin-top: 2px" >
2022-07-28 02:41:26 +00:00
< div class = "row" >
< div class = "col-sm-3 col-lg-2 form-group !m-0" > < span > < / span > < / div >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-3 form-group !mr-1" style = "margin-left: -11px" >
2022-07-28 02:41:26 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< / div >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-3 form-group !mr-1" ng-if = "overridenKey.Type === ctrl.ApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM" >
2022-07-28 02:41:26 +00:00
< div class = "input-group input-group-sm" >
2022-08-12 18:22:45 +00:00
< span class = "input-group-addon required" > path on disk< / span >
2022-01-16 19:37:46 +00:00
< input
type="text"
class="form-control"
ng-model="overridenKey.Path"
placeholder="/etc/myapp/conf.d"
name="overriden_key_path_{{ index }}_{{ keyIndex }}"
ng-disabled="ctrl.formValues.Containers.length > 1"
required
ng-change="ctrl.onChangeConfigurationPath()"
data-cy="k8sAppCreate-pathOnDiskInput"
/>
< / div >
2022-07-28 02:41:26 +00:00
< span
2022-01-16 19:37:46 +00:00
ng-show="
kubernetesApplicationCreationForm['overriden_key_path_' + index + '_' + keyIndex].$invalid ||
ctrl.state.duplicates.configurationPaths.refs[index + '_' + keyIndex] !== undefined
"
2021-09-22 04:01:28 +00:00
>
2022-09-14 23:09:19 +00:00
< div class = "input-group input-group-sm text-warning" ng-if = "overridenKey.Type === ctrl.ApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM" >
2022-07-28 02:41:26 +00:00
< div
class="small"
style="margin-top: 5px"
ng-show="
kubernetesApplicationCreationForm['overriden_key_path_' + index + '_' + keyIndex].$invalid ||
ctrl.state.duplicates.configurationPaths.refs[index + '_' + keyIndex] !== undefined
"
>
< ng-messages for = "kubernetesApplicationCreationForm['overriden_key_path_' + index + '_' + keyIndex].$error" >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" ng-message = "required"
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Path is required.< /p
>
2022-07-28 02:41:26 +00:00
< / ng-messages >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" ng-if = "ctrl.state.duplicates.configurationPaths.refs[index + '_' + keyIndex] !== undefined"
2022-07-28 02:41:26 +00:00
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > This path is already used.< /p
>
< / div >
< / div >
< / span >
< / div >
< div class = "col-sm-4 form-group" >
< div class = "input-group btn-group btn-group-sm" >
< label class = "btn btn-light" ng-model = "overridenKey.Type" uib-btn-radio = "ctrl.ApplicationConfigurationFormValueOverridenKeyTypes.ENVIRONMENT" >
< pr-icon icon = "'list'" feather = "true" > < / pr-icon > Environment
< / label >
< label class = "btn btn-light" ng-model = "overridenKey.Type" uib-btn-radio = "ctrl.ApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM" >
< pr-icon icon = "'file-text'" feather = "true" > < / pr-icon > Filesystem
< / label >
2022-01-16 19:37:46 +00:00
< / div >
2021-09-22 04:01:28 +00:00
< / div >
< / div >
2021-09-07 00:37:26 +00:00
< / div >
2020-07-05 23:21:03 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- !has - override -->
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- !config - element -->
<!-- #endregion -->
2021-09-22 04:01:28 +00:00
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Persisting data < / div >
2022-01-16 19:37:46 +00:00
<!-- #region PERSISTED FOLDERS -->
< div class = "form-group" ng-if = "!ctrl.storageClassAvailable()" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
< pr-icon icon = "'info'" mode = "'primary'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
No storage option is available to persist data, contact your administrator to enable a storage option.
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.storageClassAvailable()" >
2022-08-12 18:22:45 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< span
2022-08-12 18:22:45 +00:00
class="label label-default interactive vertical-center"
2022-01-17 05:53:32 +00:00
style="margin-left: 10px"
2022-01-16 19:37:46 +00:00
ng-click="ctrl.addPersistedFolder()"
ng-if="ctrl.isAddPersistentFolderButtonShowed()"
data-cy="k8sAppCreate-addPersistentFolderButton"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'plus'" mode = "'alt'" size = "'sm'" feather = "true" > < / pr-icon > add persisted folder
< / span >
< / div >
< div class = "col-sm-12" style = "margin-top: 5px" ng-if = "ctrl.allQuotasExhaustedAndNoVolumesAvailable()" >
2022-08-12 18:22:45 +00:00
< span class = "small text-muted vertical-center" >
2022-07-11 02:05:23 +00:00
< 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.
2021-09-22 04:01:28 +00:00
< / span >
< / div >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-inline" style = "margin-top: 10px" ng-repeat = "persistedFolder in ctrl.formValues.PersistedFolders" >
< div style = "margin-top: 2px" >
2022-01-16 19:37:46 +00:00
< div class = "input-group col-sm-3 input-group-sm" ng-class = "{ striked: persistedFolder.NeedsDeletion }" >
2022-08-12 18:22:45 +00:00
< span class = "input-group-addon required" > path in container< / span >
2022-01-16 19:37:46 +00:00
< input
type="text"
class="form-control"
name="persisted_folder_path_{{ $index }}"
ng-model="persistedFolder.ContainerPath"
ng-change="ctrl.onChangePersistedFolderPath()"
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
placeholder="/data"
required
data-cy="k8sAppCreate-containerPathInput_{{ $index }}"
/>
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "input-group col-sm-2 input-group-sm" >
< span
class="btn-group btn-group-sm"
ng-class="{ striked: persistedFolder.NeedsDeletion }"
ng-if="
!ctrl.isEditAndExistingPersistedFolder($index) & &
ctrl.application.ApplicationType !== ctrl.ApplicationTypes.STATEFULSET & &
ctrl.formValues.Containers.length < = 1
"
>
< label
2022-08-12 18:22:45 +00:00
class="btn btn-light"
2022-01-16 19:37:46 +00:00
ng-model="persistedFolder.UseNewVolume"
uib-btn-radio="true"
ng-change="ctrl.useNewVolume($index)"
ng-disabled="ctrl.isNewVolumeButtonDisabled($index)"
>New volume< /label
>
< label
2022-08-12 18:22:45 +00:00
class="btn btn-light"
2022-01-16 19:37:46 +00:00
ng-model="persistedFolder.UseNewVolume"
uib-btn-radio="false"
ng-change="ctrl.useExistingVolume($index)"
ng-disabled="ctrl.isExistingVolumeButtonDisabled()"
>Existing volume< /label
>
< / span >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "input-group col-sm-3 input-group-sm" ng-class = "{ striked: persistedFolder.NeedsDeletion }" ng-if = "persistedFolder.UseNewVolume" >
2022-08-12 18:22:45 +00:00
< span class = "input-group-addon required" > requested size< / span >
2022-01-16 19:37:46 +00:00
< input
type="number"
2022-08-12 18:22:45 +00:00
class="form-control !rounded-none"
2022-01-16 19:37:46 +00:00
name="persisted_folder_size_{{ $index }}"
ng-model="persistedFolder.Size"
placeholder="20"
2022-08-12 18:22:45 +00:00
min="0"
2022-01-16 19:37:46 +00:00
required
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
2022-07-11 02:05:23 +00:00
ng-change="ctrl.onChangeVolumeRequestedSize()"
2022-01-16 19:37:46 +00:00
/>
2022-08-12 18:22:45 +00:00
< span class = "input-group-addon !p-0 !rounded-r-[5px]" >
2022-01-16 19:37:46 +00:00
< select
2022-08-12 18:22:45 +00:00
class="form-control w-12 !h-[28px] !border-none !rounded-r-[5px] text-xs"
2022-01-16 19:37:46 +00:00
ng-model="persistedFolder.SizeUnit"
2022-08-12 18:22:45 +00:00
ng-style="{ height: '100%', cursor: ctrl.isEditAndExistingPersistedFolder($index) ? 'not-allowed' : 'auto' }"
2022-01-16 19:37:46 +00:00
ng-options="unit for unit in ctrl.state.availableSizeUnits"
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
2022-07-11 02:05:23 +00:00
ng-change="ctrl.onChangeVolumeRequestedSize()"
2022-01-16 19:37:46 +00:00
>< / select >
< / span >
< / div >
< div class = "input-group col-sm-2 input-group-sm" ng-class = "{ striked: persistedFolder.NeedsDeletion }" ng-if = "persistedFolder.UseNewVolume" >
< span class = "input-group-addon" > storage< / span >
< select
ng-if="ctrl.hasMultipleStorageClassesAvailable()"
class="form-control"
ng-model="persistedFolder.StorageClass"
ng-options="storageClass as storageClass.Name for storageClass in ctrl.storageClasses"
ng-disabled="ctrl.state.isEdit || ctrl.formValues.Containers.length > 1"
data-cy="k8sAppCreate-storageSelect_{{ $index }}"
>< / select >
< input
ng-if="!ctrl.hasMultipleStorageClassesAvailable()"
type="text"
class="form-control"
disabled
ng-model="persistedFolder.StorageClass.Name"
data-cy="k8sAppCreate-storageClassNameInput_{{ $index }}"
/>
< / div >
< div class = "input-group col-sm-5 input-group-sm" ng-if = "!persistedFolder.UseNewVolume" ng-class = "{ striked: persistedFolder.NeedsDeletion }" >
< span class = "input-group-addon" > volume< / span >
< select
class="form-control"
name="existing_volumes_{{ $index }}"
ng-model="ctrl.formValues.PersistedFolders[$index].ExistingVolume"
ng-options="vol as vol.PersistentVolumeClaim.Name for vol in ctrl.availableVolumes"
ng-change="ctrl.onChangeExistingVolumeSelection()"
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
required
>
< option selected disabled hidden value = "" > Select a volume< / option >
< / select >
< / div >
< div class = "input-group col-sm-1 input-group-sm" >
< div ng-if = "!ctrl.isEditAndStatefulSet() && !ctrl.state.useExistingVolume[$index] && ctrl.formValues.Containers.length <= 1" >
< button
ng-if="!persistedFolder.NeedsDeletion"
2022-08-12 18:22:45 +00:00
class="btn btn-sm btn-dangerlight !ml-0 h-[30px]"
2022-01-16 19:37:46 +00:00
type="button"
ng-click="ctrl.removePersistedFolder($index)"
data-cy="k8sAppCreate-rmPersistentFolderButton"
>
2022-08-12 18:22:45 +00:00
< pr-icon icon = "'trash-2'" feather = "true" size = "'md'" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< button
ng-if="persistedFolder.NeedsDeletion"
class="btn btn-sm btn-primary"
type="button"
ng-click="ctrl.restorePersistedFolder($index)"
data-cy="k8sAppCreate-restorePersistentButton"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'rotate-cw'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< / div >
2021-09-22 04:01:28 +00:00
< / div >
< / div >
< div
2022-08-12 18:22:45 +00:00
class="flex flex-row gap-x-1"
2021-09-22 04:01:28 +00:00
ng-show="
2022-01-16 19:37:46 +00:00
kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$invalid ||
ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined ||
kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$invalid ||
2022-07-11 02:05:23 +00:00
ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined ||
2022-01-16 19:37:46 +00:00
kubernetesApplicationCreationForm['existing_volumes_' + $index].$invalid ||
ctrl.state.duplicates.existingVolumes.refs[$index] !== undefined
2021-09-22 04:01:28 +00:00
"
>
2022-01-16 19:37:46 +00:00
< div class = "input-group col-sm-3 input-group-sm" >
2021-09-22 04:01:28 +00:00
< div
2022-09-14 23:09:19 +00:00
class="small text-warning"
2022-01-17 05:53:32 +00:00
style="margin-top: 5px"
2021-09-22 04:01:28 +00:00
ng-show="
2022-01-16 19:37:46 +00:00
kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$invalid || ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined
2021-09-22 04:01:28 +00:00
"
2021-09-07 00:37:26 +00:00
>
2022-01-16 19:37:46 +00:00
< ng-messages for = "kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$error" >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" ng-message = "required" > < pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Path is required.< / p >
2021-09-22 04:01:28 +00:00
< / ng-messages >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" ng-if = "ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined"
2022-07-11 02:05:23 +00:00
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > This path is already defined.< /p
2022-01-16 19:37:46 +00:00
>
< / div >
< / div >
2022-08-12 18:22:45 +00:00
< div class = "input-group col-sm-offset-2 col-sm-3 input-group-sm" >
2022-07-11 02:05:23 +00:00
< div
2022-09-14 23:09:19 +00:00
class="small text-warning"
2022-07-11 02:05:23 +00:00
style="margin-top: 5px"
ng-show="
kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$invalid || ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined
"
>
2022-01-16 19:37:46 +00:00
< ng-messages for = "kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$error" >
2022-08-12 18:22:45 +00:00
< 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
>
2022-01-16 19:37:46 +00:00
< / ng-messages >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" ng-if = "ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined" >
2022-07-11 02:05:23 +00:00
< 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
{{ persistedFolder.StorageClass.Name }}
< / p >
2022-01-16 19:37:46 +00:00
< / div >
< div
class="small text-warning"
ng-show="kubernetesApplicationCreationForm['existing_volumes_' + $index].$invalid || ctrl.state.duplicates.existingVolumes.refs[$index] !== undefined"
>
< ng-messages for = "kubernetesApplicationCreationForm['existing_volumes_' + $index].$error" >
2022-07-11 02:05:23 +00:00
< p ng-message = "required" > < pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Volume is required.< / p >
2022-01-16 19:37:46 +00:00
< / ng-messages >
< p ng-if = "ctrl.state.duplicates.existingVolumes.refs[$index] !== undefined"
2022-07-11 02:05:23 +00:00
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > This volume is already used.< /p
2021-09-22 04:01:28 +00:00
>
< / div >
2021-09-07 00:37:26 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "input-group col-sm-1 input-group-sm" > < / div >
2021-09-07 00:37:26 +00:00
< / div >
2021-02-26 15:50:33 +00:00
< / div >
2020-07-05 23:21:03 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- #endregion -->
2021-09-07 00:37:26 +00:00
2022-01-16 19:37:46 +00:00
<!-- #region DATA ACCESS POLICY -->
< div ng-if = "ctrl.showDataAccessPolicySection()" >
< div class = "form-group" >
< div class = "col-sm-12" >
< label class = "control-label text-left" > Data access policy< / label >
< / div >
< / div >
2021-09-07 00:37:26 +00:00
2022-01-16 19:37:46 +00:00
< div class = "form-group" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 small text-muted" > Specify how the data will be used across instances. < / div >
2022-01-16 19:37:46 +00:00
< / div >
2021-09-07 00:37:26 +00:00
2022-01-16 19:37:46 +00:00
<!-- access policy options -->
2022-08-22 08:55:48 +00:00
< div class = "form-group" >
< div class = "col-sm-12" >
< div class = "boxselector_wrapper" >
< div
ng-if="
(!ctrl.state.isEdit & & !ctrl.state.persistedFoldersUseExistingVolumes) ||
(ctrl.state.isEdit & & ctrl.formValues.DataAccessPolicy === ctrl.ApplicationDataAccessPolicies.ISOLATED)
"
2021-09-22 04:01:28 +00:00
>
2022-08-22 08:55:48 +00:00
< input
type="radio"
id="data_access_isolated"
ng-value="ctrl.ApplicationDataAccessPolicies.ISOLATED"
ng-model="ctrl.formValues.DataAccessPolicy"
ng-change="ctrl.resetDeploymentType()"
/>
< label for = "data_access_isolated" >
< div class = "boxselector_header" >
< pr-icon icon = "'svg-cubes'" > < / pr-icon >
Isolated
< / div >
< p > Application will be deployed as a StatefulSet with each instantiating their own data< / p >
< / label >
< / div >
< div
style="color: #767676"
ng-if="
(ctrl.state.isEdit & & ctrl.formValues.DataAccessPolicy === ctrl.ApplicationDataAccessPolicies.SHARED) || ctrl.state.persistedFoldersUseExistingVolumes
"
2021-09-24 01:00:55 +00:00
>
2022-08-22 08:55:48 +00:00
< input type = "radio" id = "data_access_isolated" disabled / >
< label
for="data_access_isolated"
tooltip-append-to-body="true"
tooltip-placement="bottom"
tooltip-class="portainer-tooltip"
uib-tooltip="Changing the data access policy is not allowed"
style="cursor: pointer; border-color: #767676"
>
< div class = "boxselector_header" >
< pr-icon icon = "'svg-cubes'" > < / pr-icon >
Isolated
< / div >
< p > Application will be deployed as a StatefulSet with each instantiating their own data< / p >
< / label >
< / div >
< div ng-if = "!ctrl.state.isEdit || (ctrl.state.isEdit && ctrl.formValues.DataAccessPolicy === ctrl.ApplicationDataAccessPolicies.SHARED)" >
< input
type="radio"
id="data_access_shared"
ng-value="ctrl.ApplicationDataAccessPolicies.SHARED"
ng-model="ctrl.formValues.DataAccessPolicy"
ng-change="ctrl.resetDeploymentType()"
/>
< label for = "data_access_shared" >
< div class = "boxselector_header" >
< pr-icon icon = "'box'" feather = "true" > < / pr-icon >
Shared
< / div >
< p > Application will be deployed as a Deployment with a shared storage access< / p >
< / label >
< / div >
< div style = "color: #767676" ng-if = "ctrl.state.isEdit && ctrl.formValues.DataAccessPolicy === ctrl.ApplicationDataAccessPolicies.ISOLATED" >
< input type = "radio" id = "data_access_shared" disabled / >
< label
for="data_access_shared"
tooltip-append-to-body="true"
tooltip-placement="bottom"
tooltip-class="portainer-tooltip"
uib-tooltip="Changing the data access policy is not allowed"
style="cursor: pointer; border-color: #767676"
>
< div class = "boxselector_header" >
< pr-icon icon = "'sliders'" feather = "true" > < / pr-icon >
Shared
< / div >
< p > Application will be deployed as a Deployment with a shared storage access< / p >
< / label >
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2021-09-07 00:37:26 +00:00
< / div >
< / div >
2022-01-16 19:37:46 +00:00
<!-- !access policy options -->
< / div >
<!-- #endregion -->
2021-09-07 00:37:26 +00:00
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Resource reservations < / div >
2022-01-16 19:37:46 +00:00
<!-- #region RESOURCE RESERVATIONS -->
< div class = "form-group" ng-if = "!ctrl.state.resourcePoolHasQuota" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
< pr-icon icon = "'info'" mode = "'primary'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
Resource reservations are applied per instance of the application.
< / div >
< / div >
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.state.resourcePoolHasQuota && !ctrl.resourceQuotaCapacityExceeded()" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
< pr-icon icon = "'info'" mode = "'primary'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
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 >
2021-02-26 15:50:33 +00:00
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.state.resourcePoolHasQuota && ctrl.resourceQuotaCapacityExceeded()" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'danger'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
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.
< / div >
< / div >
2021-09-07 00:37:26 +00:00
2022-01-16 19:37:46 +00:00
<!-- memory - limit - input -->
< div
2022-08-12 18:22:45 +00:00
class="form-group flex"
2022-01-16 19:37:46 +00:00
ng-if="
(!ctrl.state.resourcePoolHasQuota || (ctrl.state.resourcePoolHasQuota & & !ctrl.resourceQuotaCapacityExceeded())) & & ctrl.formValues.Containers.length < = 1
"
>
2022-08-12 18:22:45 +00:00
< label for = "memory-limit" class = "col-sm-3 col-lg-2 control-label text-left flex flex-row items-center" >
Memory limit (MB)
2022-01-16 19:37:46 +00:00
< portainer-tooltip
2022-07-03 23:21:25 +00:00
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.'"
2022-01-16 19:37:46 +00:00
>
< / portainer-tooltip >
< / label >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-6" >
2022-01-16 19:37:46 +00:00
< slider model = "ctrl.formValues.MemoryLimit" floor = "ctrl.state.sliders.memory.min" ceil = "ctrl.state.sliders.memory.max" step = "128" > < / slider >
< / div >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-2 vertical-center" >
2022-01-16 19:37:46 +00:00
< input
name="memory_limit"
ng-model="ctrl.formValues.MemoryLimit"
type="number"
min="{{ ctrl.state.sliders.memory.min }}"
max="{{ ctrl.state.sliders.memory.max }}"
class="form-control"
id="memory-limit"
required
data-cy="k8sAppCreate-memoryLimit"
/>
< / div >
< / div >
< div class = "form-group" ng-show = "kubernetesApplicationCreationForm.memory_limit.$invalid" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-3 col-lg-2" > < / div >
2022-09-14 23:09:19 +00:00
< div class = "col-sm-8 small text-warning" >
2022-01-16 19:37:46 +00:00
< div ng-messages = "kubernetesApplicationCreationForm.memory_limit.$error" >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center"
2022-07-11 02:05:23 +00:00
>< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Value must be between {{ ctrl.state.sliders.memory.min }} and
2022-01-16 19:37:46 +00:00
{{ ctrl.state.sliders.memory.max }}
< / p >
< / div >
< / div >
< / div >
<!-- !memory - limit - input -->
<!-- cpu - limit - input -->
< div
2022-08-12 18:22:45 +00:00
class="form-group flex"
2022-01-16 19:37:46 +00:00
ng-if="
(!ctrl.state.resourcePoolHasQuota || (ctrl.state.resourcePoolHasQuota & & !ctrl.resourceQuotaCapacityExceeded())) & & ctrl.formValues.Containers.length < = 1
"
>
2022-08-12 18:22:45 +00:00
< label for = "cpu-limit" class = "col-sm-3 col-lg-2 control-label text-left flex flex-row items-center" >
CPU limit
2022-01-16 19:37:46 +00:00
< portainer-tooltip
2022-07-03 23:21:25 +00:00
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.'"
2022-01-16 19:37:46 +00:00
>
< / portainer-tooltip >
< / label >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-8" >
2022-01-16 19:37:46 +00:00
< slider model = "ctrl.formValues.CpuLimit" floor = "ctrl.state.sliders.cpu.min" ceil = "ctrl.state.sliders.cpu.max" step = "0.10" precision = "2" > < / slider >
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2021-09-07 00:37:26 +00:00
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.nodeLimitsOverflow()" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-3 col-lg-2" > < / div >
< div class = "col-sm-8 small text-muted" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'danger'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
These reservations would exceed the resources currently available in the cluster.
2021-09-07 00:37:26 +00:00
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- !cpu - limit - input -->
<!-- #endregion -->
2021-09-07 00:37:26 +00:00
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Deployment < / div >
2022-01-16 19:37:46 +00:00
<!-- #region DEPLOYMENT -->
2021-09-22 04:01:28 +00:00
< div class = "form-group" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 small text-muted" > Select how you want to deploy your application inside the cluster. < / div >
2020-07-05 23:21:03 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- deployment options -->
2022-08-22 08:55:48 +00:00
< div class = "form-group" >
< div class = "col-sm-12" >
< div class = "boxselector_wrapper" >
< div >
< input
type="radio"
id="deployment_replicated"
ng-value="ctrl.ApplicationDeploymentTypes.REPLICATED"
ng-model="ctrl.formValues.DeploymentType"
data-cy="k8sAppCreate-replicatedDeploymentButton"
/>
< label for = "deployment_replicated" >
< div class = "boxselector_header" >
< pr-icon icon = "'sliders'" feather = "true" > < / pr-icon >
Replicated
< / div >
< p > Run one or multiple instances of this container< / p >
< / label >
< / div >
< div ng-if = "!ctrl.supportGlobalDeployment()" >
< input type = "radio" id = "deployment_global" disabled / >
< label
for="deployment_global"
tooltip-append-to-body="true"
tooltip-placement="bottom"
tooltip-class="portainer-tooltip"
uib-tooltip="The storage or access policy used for persisted folders cannot be used with this option"
>
< div class = "boxselector_header" >
< 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 >
< / label >
< / div >
< div ng-if = "ctrl.supportGlobalDeployment()" >
< input
type="radio"
id="deployment_global"
ng-value="ctrl.ApplicationDeploymentTypes.GLOBAL"
ng-model="ctrl.formValues.DeploymentType"
ng-click="ctrl.unselectAutoScaler()"
data-cy="k8sAppCreate-globalDeployButton"
/>
< label for = "deployment_global" >
< div class = "boxselector_header" >
< 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 sdfh< / p >
< / label >
< / div >
2021-02-26 15:50:33 +00:00
< / div >
2020-07-05 23:21:03 +00:00
< / div >
< / div >
2022-01-16 19:37:46 +00:00
<!-- !deployment options -->
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
<!-- replica count -->
2022-09-14 23:09:19 +00:00
< div class = "form-group" ng-if = "ctrl.formValues.DeploymentType === ctrl.ApplicationDeploymentTypes.REPLICATED" >
< label for = "replica_count" class = "col-sm-1 control-label text-left" > Instance count< / label >
< div class = "col-sm-2" >
2022-01-16 19:37:46 +00:00
< input
type="number"
name="replica_count"
class="form-control"
min="1"
max="9999"
placeholder="1"
ng-model="ctrl.formValues.ReplicaCount"
ng-disabled="!ctrl.supportScalableReplicaDeployment()"
ng-change="ctrl.enforceReplicaCountMinimum()"
required
data-cy="k8sAppCreate-replicaCountInput"
/>
2022-09-14 23:09:19 +00:00
< div class = "help-block" ng-if = "kubernetesApplicationCreationForm['replica_count'].$invalid" >
< div class = "small text-warning whitespace-nowrap" >
< ng-messages for = "kubernetesApplicationCreationForm['replica_count'].$error" >
< 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 >
2022-01-16 19:37:46 +00:00
< / div >
2020-07-05 23:21:03 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- !replica count -->
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
< div
class="form-group"
ng-if="!ctrl.resourceReservationsOverflow() & & ctrl.formValues.ReplicaCount > 1 & & (ctrl.formValues.CpuLimit !== 0 || ctrl.formValues.MemoryLimit !== 0)"
>
2022-08-12 18:22:45 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.resourceReservationsOverflow()" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'danger'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
This application would exceed available resources. Please review resource reservations or the instance count.
2021-09-22 04:01:28 +00:00
< / div >
< / div >
2022-07-11 02:05:23 +00:00
< div class = "form-group" ng-if = "ctrl.state.storages.quotaExceeded" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
2022-07-11 02:05:23 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "!ctrl.supportScalableReplicaDeployment()" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 small text-muted vertical-center" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'warning'" feather = "true" > < / pr-icon >
2022-08-12 18:22:45 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- #endregion -->
2021-09-22 04:01:28 +00:00
2022-01-16 19:37:46 +00:00
<!-- #region AUTO SCALING -->
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" ng-if = "ctrl.formValues.DeploymentType !== ctrl.ApplicationDeploymentTypes.GLOBAL" > Auto-scaling < / div >
2021-09-22 04:01:28 +00:00
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.formValues.DeploymentType !== ctrl.ApplicationDeploymentTypes.GLOBAL && ctrl.state.useServerMetrics" >
< div class = "col-sm-12" >
2022-08-12 18:22:45 +00:00
< 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" >
2022-01-16 19:37:46 +00:00
< input
type="checkbox"
class="form-control"
name="enable_auto_scaling"
ng-model="ctrl.formValues.AutoScaler.IsUsed"
data-cy="k8sAppCreate-autoScaleCheckbox"
/>
2022-08-12 18:22:45 +00:00
< span class = "slider round" > < / span >
2021-09-07 00:37:26 +00:00
< / label >
< / div >
2020-08-07 04:40:24 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "form-group" ng-if = "ctrl.formValues.DeploymentType !== ctrl.ApplicationDeploymentTypes.GLOBAL && !ctrl.state.useServerMetrics" >
< div class = "col-sm-12 small text-muted" >
2022-01-17 05:53:32 +00:00
< p ng-if = "!ctrl.isAdmin" > This feature is currently disabled and must be enabled by an administrator user. < / p >
2022-01-16 19:37:46 +00:00
< p ng-if = "ctrl.isAdmin" >
Server metrics features must be enabled in the
2022-07-22 02:14:31 +00:00
< a ui-sref = "kubernetes.cluster.setup" class = "ctrl.isAdmin" > environment configuration view< / a > .
2022-01-16 19:37:46 +00:00
< / p >
< / div >
2020-07-05 23:21:03 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "form-inline" ng-if = "ctrl.formValues.DeploymentType !== ctrl.ApplicationDeploymentTypes.GLOBAL && ctrl.formValues.AutoScaler.IsUsed" >
2022-08-22 20:54:40 +00:00
< div class = "row" >
< div class = "col-sm-4 pl-0" >
< label class = "control-label text-left pb-2" for = "auto_scaler_min" > Minimum instances< / label >
< div class = "input-group input-group-sm" style = "width: 100%" >
< input
type="number"
class="form-control"
name="auto_scaler_min"
min="0"
ng-max="ctrl.formValues.AutoScaler.MaxReplicas"
ng-model="ctrl.formValues.AutoScaler.MinReplicas"
data-cy="k8sAppCreate-autoScaleMin"
required
/>
< / div >
< span ng-show = "kubernetesApplicationCreationForm['auto_scaler_min'].$invalid" >
2022-09-14 23:09:19 +00:00
< div class = "small text-warning" style = "margin-top: 5px" >
2022-08-22 20:54:40 +00:00
< ng-messages for = "kubernetesApplicationCreationForm['auto_scaler_min'].$error" >
< p ng-message = "required" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Minimum instances is required.
< / p >
< p ng-message = "min" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Minimum instances must be greater than 0.
< / p >
< p ng-message = "max" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Minimum instances must be smaller than maximum instances.
< / p >
< / ng-messages >
< / div >
< / span >
< / div >
< div class = "col-sm-4 pl-0" >
< label class = "control-label text-left pb-2" for = "auto_scaler_max" > Maximum instances< / label >
< div class = "input-group input-group-sm" style = "width: 100%" >
< input
type="number"
class="form-control"
name="auto_scaler_max"
ng-min="ctrl.formValues.AutoScaler.MinReplicas"
ng-model="ctrl.formValues.AutoScaler.MaxReplicas"
/>
< / div >
< span ng-show = "kubernetesApplicationCreationForm['auto_scaler_max'].$invalid || ctrl.autoScalerOverflow()" >
2022-09-14 23:09:19 +00:00
< div class = "small text-warning" style = "margin-top: 5px" >
2022-08-22 20:54:40 +00:00
< ng-messages for = "kubernetesApplicationCreationForm['auto_scaler_max'].$error" >
< p ng-message = "required" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Maximum instances is required.
< / p >
< p ng-message = "min" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Maximum instances must be greater than minimum instances.
< / p >
< / ng-messages >
< / div >
< / span >
< / div >
< div class = "col-sm-4 pl-0" >
< label class = "control-label text-left pb-2" for = "auto_scaler_cpu" >
Target CPU usage (< b > %< / b > )
< portainer-tooltip message = "'The autoscaler will ensure enough instances are running to maintain an average CPU usage across all instances.'" >
< / portainer-tooltip >
< / label >
< div class = "input-group input-group-sm" style = "width: 100%" >
< input
type="number"
class="form-control"
name="auto_scaler_cpu"
ng-model="ctrl.formValues.AutoScaler.TargetCPUUtilization"
min="1"
max="100"
required
data-cy="k8sAppCreate-targetCPUInput"
/>
< / div >
< span ng-show = "kubernetesApplicationCreationForm['auto_scaler_cpu'].$invalid" >
2022-09-14 23:09:19 +00:00
< div class = "small text-warning" style = "margin-top: 5px" >
2022-08-22 20:54:40 +00:00
< ng-messages for = "kubernetesApplicationCreationForm['auto_scaler_cpu'].$error" >
< p ng-message = "required" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Target CPU usage is required.
< / p >
< p ng-message = "min" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Target CPU usage must be greater than 0.
< / p >
< p ng-message = "max" class = "vertical-center" >
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > Target CPU usage must be smaller than 100.
< / p >
< / ng-messages >
< / div >
< / span >
< / div >
< / div >
2022-01-16 19:37:46 +00:00
2022-01-17 05:53:32 +00:00
< div class = "form-group" ng-if = "ctrl.autoScalerOverflow()" style = "margin-bottom: 10px" >
2022-01-16 19:37:46 +00:00
< div class = "col-sm-12 small text-danger" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'danger'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
This application would exceed available resources. Please review resource reservations or the maximum instance count of the auto-scaling policy.
< / div >
< / div >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- #endregion -->
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
< div ng-if = "ctrl.formValues.DeploymentType === ctrl.ApplicationDeploymentTypes.REPLICATED" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" > Placement preferences and constraints < / div >
2020-07-05 23:21:03 +00:00
2022-01-16 19:37:46 +00:00
<!-- #region PLACEMENTS -->
< div class = "form-group" >
2022-08-12 18:22:45 +00:00
< div class = "col-sm-12 vertical-center pt-2.5" >
< label class = "control-label text-left !pt-0" > Placement rules< / label >
2022-07-11 02:05:23 +00:00
< 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
2022-01-16 19:37:46 +00:00
< / span >
< / div >
2020-07-05 23:21:03 +00:00
2022-08-12 18:22:45 +00:00
< 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 >
2022-01-16 19:37:46 +00:00
< / div >
2021-08-31 21:08:01 +00:00
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-inline" style = "margin-top: 10px" >
< div ng-repeat-start = "placement in ctrl.formValues.Placements" style = "margin-top: 2px" >
2022-01-16 19:37:46 +00:00
< div class = "col-sm-5 input-group" ng-class = "{ striked: placement.NeedsDeletion }" >
< select
2022-08-12 18:22:45 +00:00
class="form-control !rounded"
2022-01-16 19:37:46 +00:00
ng-model="placement.Label"
ng-options="label as (label.Key | kubernetesNodeLabelHumanReadbleText) for label in ctrl.nodesLabels"
ng-change="ctrl.onChangePlacementLabel($index)"
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
data-cy="k8sAppCreate-placementLabel_{{ $index }}"
>
< / select >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< div class = "col-sm-5 input-group" ng-class = "{ striked: placement.NeedsDeletion }" >
< select
2022-08-12 18:22:45 +00:00
class="form-control !rounded"
2022-01-16 19:37:46 +00:00
ng-model="placement.Value"
ng-options="value for value in placement.Label.Values"
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
data-cy="k8sAppCreate-placementName_{{ $index }}"
>
< / select >
< / div >
< div class = "col-sm-1 input-group" >
< button
ng-if="!placement.NeedsDeletion"
2022-08-12 18:22:45 +00:00
class="btn btn-md btn-dangerlight btn-only-icon !ml-0"
2022-01-16 19:37:46 +00:00
type="button"
ng-click="ctrl.removePlacement($index)"
data-cy="k8sAppCreate-deletePlacementButton"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'trash-2'" size = "'md'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< button
ng-if="placement.NeedsDeletion"
2022-08-12 18:22:45 +00:00
class="btn btn-sm btn-light btn-only-icon !ml-0"
2022-01-16 19:37:46 +00:00
type="button"
ng-click="ctrl.restorePlacement($index)"
data-cy="k8sAppCreate-restorePlacementButton"
>
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'rotate-cw'" size = "'md'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
< / button >
< / div >
< / div >
< div ng-repeat-end ng-show = "ctrl.state.duplicates.placements.refs[$index] !== undefined" >
< div class = "col-sm-5 input-group" >
2022-09-14 23:09:19 +00:00
< div class = "small text-warning" style = "margin-top: 5px" ng-if = "ctrl.state.duplicates.placements.refs[$index] !== undefined" >
2022-08-12 18:22:45 +00:00
< p class = "vertical-center" ng-if = "ctrl.state.duplicates.placements.refs[$index] !== undefined" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-triangle'" mode = "'warning'" feather = "true" > < / pr-icon > This label is already defined.
2022-01-16 19:37:46 +00:00
< / p >
2021-09-22 04:01:28 +00:00
< / div >
< / div >
2022-01-16 19:37:46 +00:00
< / div >
< / div >
< / div >
< div ng-if = "ctrl.showPlacementPolicySection()" >
< div class = "form-group" >
< div class = "col-sm-12" >
< label class = "control-label text-left" > Placement policy< / label >
< / div >
< / div >
< div class = "form-group" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 small text-muted" > Specify the policy associated to the placement rules. < / div >
2022-01-16 19:37:46 +00:00
< / div >
<!-- placement policy options -->
2022-08-22 08:55:48 +00:00
< div class = "form-group" ng-if = "ctrl.formValues.Placements.length" >
< div class = "col-sm-12" >
< div class = "boxselector_wrapper" >
< div >
< input
type="radio"
id="placement_hard"
ng-value="ctrl.ApplicationPlacementTypes.MANDATORY"
ng-model="ctrl.formValues.PlacementType"
data-cy="k8sAppCreate-mandatoryPlacementButton"
/>
< label for = "placement_hard" >
< div class = "boxselector_header" >
< pr-icon icon = "'sliders'" feather = "true" > < / pr-icon >
Mandatory
< / div >
< p > Schedule this application < b > ONLY< / b > on nodes that match < b > ALL< / b > Rules< / p >
< / label >
< / div >
< div >
< input
type="radio"
id="placement_soft"
ng-value="ctrl.ApplicationPlacementTypes.PREFERRED"
ng-model="ctrl.formValues.PlacementType"
data-cy="k8sAppCreate-prefferedPlacementButton"
/>
< label for = "placement_soft" >
< div class = "boxselector_header" >
< pr-icon icon = "'align-justify'" feather = "true" > < / pr-icon >
Preferred
< / div >
< p > Schedule this application on nodes that match the rules if possible< / p >
< / label >
< / div >
2021-09-07 00:37:26 +00:00
< / div >
< / div >
< / div >
2022-01-16 19:37:46 +00:00
<!-- !placement policy options -->
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- #endregion -->
2021-09-22 04:01:28 +00:00
< / div >
2020-08-12 23:30:23 +00:00
2022-01-16 19:37:46 +00:00
<!-- kubernetes services options -->
< kube-services-view form-values = "ctrl.formValues" is-edit = "ctrl.state.isEdit" loadbalancer-enabled = "ctrl.publishViaLoadBalancerEnabled()" > < / kube-services-view >
<!-- kubernetes services options -->
2021-09-22 04:01:28 +00:00
2022-01-16 19:37:46 +00:00
<!-- summary -->
< kubernetes-summary-view
ng-if="!(!kubernetesApplicationCreationForm.$valid || ctrl.isDeployUpdateButtonDisabled() || !ctrl.state.pullImageValidity)"
form-values="ctrl.formValues"
old-form-values="ctrl.savedFormValues"
>< / kubernetes-summary-view >
2020-07-05 23:21:03 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< / div >
< / div >
< div ng-if = "ctrl.isExternalApplication()" >
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" ng-if = "ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM" > Namespace < / div >
2022-01-16 19:37:46 +00:00
<!-- #region NAMESPACE -->
< div class = "form-group" ng-if = "ctrl.formValues.ResourcePool" >
< label for = "resource-pool-selector" class = "col-sm-1 control-label text-left" > Namespace< / label >
< div class = "col-sm-11" >
< select
class="form-control"
id="resource-pool-selector"
ng-model="ctrl.formValues.ResourcePool"
ng-options="resourcePool.Namespace.Name for resourcePool in ctrl.resourcePools"
ng-change="ctrl.onResourcePoolSelectionChange()"
ng-disabled="ctrl.state.isEdit"
data-cy="k8sAppCreate-nsSelect"
>< / select >
2021-09-22 04:01:28 +00:00
< / div >
2022-01-16 19:37:46 +00:00
< / div >
< div class = "form-group" ng-if = "ctrl.state.resourcePoolHasQuota && ctrl.resourceQuotaCapacityExceeded() && ctrl.formValues.ResourcePool" >
< div class = "col-sm-12 small text-danger" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'danger'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
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.
< / div >
< / div >
< div class = "form-group" ng-if = "!ctrl.formValues.ResourcePool" >
< div class = "col-sm-12 small text-muted" >
2022-07-11 02:05:23 +00:00
< pr-icon icon = "'alert-circle'" mode = "'warning'" feather = "true" > < / pr-icon >
2022-01-16 19:37:46 +00:00
You do not have access to any namespace. Contact your administrator to get access to a namespace.
2021-09-07 00:37:26 +00:00
< / div >
2021-09-24 01:00:55 +00:00
< / div >
2022-01-16 19:37:46 +00:00
<!-- kubernetes services options -->
< kube-services-view form-values = "ctrl.formValues" is-edit = "ctrl.state.isEdit" loadbalancer-enabled = "ctrl.publishViaLoadBalancerEnabled()" > < / kube-services-view >
<!-- kubernetes services options -->
2021-09-07 00:37:26 +00:00
< / div >
2021-06-09 22:38:23 +00:00
2022-01-16 19:37:46 +00:00
<!-- kubernetes summary for external application -->
< kubernetes-summary-view ng-if = "ctrl.isExternalApplication()" form-values = "ctrl.formValues" old-form-values = "ctrl.savedFormValues" > < / kubernetes-summary-view >
<!-- kubernetes summary for external application -->
2022-01-17 05:53:32 +00:00
< div class = "col-sm-12 form-section-title" ng-if = "ctrl.state.appType !== ctrl.KubernetesDeploymentTypes.GIT" > Actions < / div >
2020-08-12 23:30:23 +00:00
<!-- #region ACTIONS -->
2020-07-05 23:21:03 +00:00
< div class = "form-group" >
< div class = "col-sm-12" >
< button
2021-09-07 00:37:26 +00:00
ng-if="ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM"
2020-07-05 23:21:03 +00:00
type="button"
2022-08-12 18:22:45 +00:00
class="btn btn-primary btn-sm !ml-0"
2021-10-19 00:21:54 +00:00
ng-disabled="!kubernetesApplicationCreationForm.$valid || ctrl.isDeployUpdateButtonDisabled() || !ctrl.imageValidityIsValid()"
2020-07-05 23:21:03 +00:00
ng-click="ctrl.deployApplication()"
button-spinner="ctrl.state.actionInProgress"
2021-08-26 00:05:28 +00:00
data-cy="k8sAppCreate-deployButton"
2020-07-05 23:21:03 +00:00
>
< span ng-show = "!ctrl.state.isEdit && !ctrl.state.actionInProgress" > Deploy application< / span >
< span ng-show = "!ctrl.state.isEdit && ctrl.state.actionInProgress" > Deployment in progress...< / span >
< span ng-show = "ctrl.state.isEdit && !ctrl.state.actionInProgress" > Update application< / span >
< span ng-show = "ctrl.state.isEdit && ctrl.state.actionInProgress" > Update in progress...< / span >
< / button >
< button
2021-09-07 00:37:26 +00:00
ng-if="ctrl.state.isEdit & & !ctrl.state.actionInProgress & & ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM"
2020-07-05 23:21:03 +00:00
type="button"
class="btn btn-sm btn-default"
ui-sref="kubernetes.applications.application({ name: ctrl.application.Name, namespace: ctrl.application.ResourcePool })"
2021-09-24 01:00:55 +00:00
data-cy="k8sAppCreate-appCancelButton"
2020-07-05 23:21:03 +00:00
>
2020-08-12 23:30:23 +00:00
Cancel
< / button >
2021-09-07 00:37:26 +00:00
<!-- #Web editor buttons -->
< button
class="btn btn-sm btn-primary"
ng-click="ctrl.updateApplicationViaWebEditor()"
ng-if="ctrl.state.appType === ctrl.KubernetesDeploymentTypes.CONTENT || ctrl.state.updateWebEditorInProgress"
ng-disabled="!kubernetesApplicationCreationForm.$valid || !ctrl.state.isEditorDirty || ctrl.state.updateWebEditorInProgress"
2022-01-17 05:53:32 +00:00
style="margin-top: 7px; margin-left: 0"
2021-09-07 00:37:26 +00:00
button-spinner="ctrl.state.updateWebEditorInProgress"
>
< span ng-show = "!ctrl.state.updateWebEditorInProgress" > Update the application< / span >
< span ng-show = "ctrl.state.updateWebEditorInProgress" > Update in progress...< / span >
< / button >
2020-07-05 23:21:03 +00:00
< / div >
< / div >
2020-08-12 23:30:23 +00:00
<!-- #endregion -->
2020-07-05 23:21:03 +00:00
< / form >
< / rd-widget-body >
< / rd-widget >
< / div >
< / div >
< / div >