feat(kube): create namespace from manifest view [EE-3479] (#7306)

Restyle create from manifest
pull/7399/head
Matt Hook 2022-08-01 16:44:56 +12:00 committed by GitHub
parent 11c778cfeb
commit ddaf9dc885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 154 additions and 90 deletions

View File

@ -79,6 +79,12 @@
background-color: var(--ui-gray-3);
}
.switch-values {
font-style: normal;
font-weight: 500;
margin-left: 5px;
}
/* Toggle */
.slider {

View File

@ -13,7 +13,7 @@
<uib-tab index="0">
<uib-tab-heading> <pr-icon icon="'code'" feather="true"></pr-icon> Deploy </uib-tab-heading>
<div class="col-sm-12 form-section-title"> Namespace </div>
<form class="form-horizontal" style="margin-top: 20px" name="deploymentForm">
<form class="form-horizontal mt-3" name="deploymentForm">
<div class="form-group" ng-if="ctrl.formValues.Namespace">
<label for="target_node" class="col-lg-2 col-sm-3 control-label text-left">Namespace</label>
<div class="col-sm-8">
@ -31,16 +31,18 @@
<portainer-tooltip message="'If you have defined namespaces in your deployment file turning this on will enforce the use of those only in the deployment'">
</portainer-tooltip>
</label>
<div class="col-sm-8">
<div class="col-sm-8 vertical-center pt-3">
<label class="switch">
<input type="checkbox" name="toggle_logo" ng-model="ctrl.formValues.namespace_toggle" />
<i></i>
<span class="slider round"></span>
</label>
<!-- <span class="ml-2 mb-1 switch-values" ng-if="ctrl.formValues.namespace_toggle">Yes</span>
<span class="ml-2 mb-1 switch-values" ng-if="!ctrl.formValues.namespace_toggle">No</span> -->
</div>
</div>
<div class="form-group" ng-if="!ctrl.formValues.Namespace">
<div class="col-sm-12 small text-muted">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px"></i>
<pr-icon icon="'alert-triangle'" feather="true" mode="'warning'"></pr-icon>
You do not have access to any namespace. Contact your administrator to get access to a namespace.
</div>
</div>
@ -103,40 +105,41 @@
</div>
<!-- editor -->
<web-editor-form
ng-if="ctrl.state.BuildMethod === ctrl.BuildMethods.WEB_EDITOR || (ctrl.state.BuildMethod === ctrl.BuildMethods.CUSTOM_TEMPLATE && ctrl.state.templateId)"
identifier="kubernetes-deploy-editor"
value="ctrl.formValues.EditorContent"
on-change="(ctrl.onChangeFileContent)"
ng-required="true"
yml="true"
placeholder="# Define or paste the content of your manifest file here"
>
<editor-description>
<div ng-show="ctrl.state.DeployType === ctrl.ManifestDeployTypes.COMPOSE">
<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.
</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>
</div>
<div ng-show="ctrl.state.DeployType === ctrl.ManifestDeployTypes.KUBERNETES">
<p class="vertical-center">
<pr-icon icon="'alert-circle'" 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>
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>
</div>
</editor-description>
</web-editor-form>
<div class="mt-4">
<web-editor-form
ng-if="ctrl.state.BuildMethod === ctrl.BuildMethods.WEB_EDITOR || (ctrl.state.BuildMethod === ctrl.BuildMethods.CUSTOM_TEMPLATE && ctrl.state.templateId)"
identifier="kubernetes-deploy-editor"
value="ctrl.formValues.EditorContent"
on-change="(ctrl.onChangeFileContent)"
ng-required="true"
yml="true"
placeholder="# Define or paste the content of your manifest file here"
>
<editor-description>
<span class="col-sm-12 text-muted small" ng-show="ctrl.state.DeployType === ctrl.ManifestDeployTypes.COMPOSE">
<p>
<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.
</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="col-sm-12 text-muted small" ng-show="ctrl.state.DeployType === ctrl.ManifestDeployTypes.KUBERNETES">
<p>
<pr-icon icon="'alert-circle'" 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>
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>
</div>
<!-- !editor -->
<!-- url -->
@ -188,7 +191,7 @@
<uib-tab index="1" disable="ctrl.state.tabLogsDisabled">
<uib-tab-heading> <pr-icon icon="'file-text'" feather="true"></pr-icon> Logs </uib-tab-heading>
<form class="form-horizontal" style="margin-top: 20px">
<form class="form-horizontal mt-3">
<div class="form-group" ng-if="ctrl.state.activeTab === 1">
<div class="col-sm-12">
<code-editor identifier="kubernetes-deploy-logs" read-only="true" yml="false" value="ctrl.errorLog"></code-editor>

View File

@ -27,15 +27,15 @@ class KubernetesDeployController {
this.isTemplateVariablesEnabled = isBE;
this.deployOptions = [
buildOption('method_kubernetes', 'fa fa-cubes', 'Kubernetes', 'Kubernetes manifest format', KubernetesDeployManifestTypes.KUBERNETES),
buildOption('method_compose', 'fab fa-docker', 'Compose', 'Docker compose format', KubernetesDeployManifestTypes.COMPOSE),
buildOption('method_kubernetes', 'svg-kubernetes', 'Kubernetes', 'Kubernetes manifest format', KubernetesDeployManifestTypes.KUBERNETES),
buildOption('method_compose', 'svg-dockercompose', 'Compose', 'Docker compose format', KubernetesDeployManifestTypes.COMPOSE),
];
this.methodOptions = [
buildOption('method_repo', 'fab fa-github', 'Git Repository', 'Use a git repository', KubernetesDeployBuildMethods.GIT),
buildOption('method_editor', 'fa fa-edit', 'Web editor', 'Use our Web editor', KubernetesDeployBuildMethods.WEB_EDITOR),
buildOption('method_url', 'fa fa-globe', 'URL', 'Specify a URL to a file', KubernetesDeployBuildMethods.URL),
buildOption('method_template', 'fa fa-rocket', 'Custom Template', 'Use a custom template', KubernetesDeployBuildMethods.CUSTOM_TEMPLATE),
buildOption('method_repo', 'svg-git', 'Git Repository', 'Use a git repository', KubernetesDeployBuildMethods.GIT),
buildOption('method_editor', 'svg-custom', 'Web editor', 'Use our Web editor', KubernetesDeployBuildMethods.WEB_EDITOR),
buildOption('method_url', 'svg-url', 'URL', 'Specify a URL to a file', KubernetesDeployBuildMethods.URL),
buildOption('method_template', 'svg-template', 'Custom Template', 'Use a custom template', KubernetesDeployBuildMethods.CUSTOM_TEMPLATE),
];
this.state = {

View File

@ -1,7 +1,7 @@
<div>
<div class="form-group">
<label for="stack_template" class="col-sm-1 control-label text-left"> Template </label>
<div class="col-sm-11">
<div class="form-group pt-3">
<label for="stack_template" class="col-sm-3 col-lg-2 control-label text-left"> Template </label>
<div class="col-sm-8 vertical-center">
<select
ng-if="$ctrl.templates.length"
class="form-control"
@ -11,7 +11,10 @@
>
<option value="" label="Select a Custom template" disabled selected="selected"> </option>
</select>
<span ng-if="!$ctrl.templates.length"> No custom templates are available. Head over to the <a ui-state="$ctrl.newTemplatePath">custom template view</a> to create one. </span>
<span class="small text-muted pt-[7px]" ng-if="!$ctrl.templates.length">
No custom templates are available. Head over to the <a class="text-blue-8 hover:underline hover:text-blue-8" ui-state="$ctrl.newTemplatePath">custom template view</a> to
create one.
</span>
</div>
</div>

View File

@ -1,6 +1,6 @@
<ng-form class="env-item form-horizontal" name="$ctrl.{{ $ctrl.formName }}">
<div class="form-group col-sm-12">
<div class="form-inline" style="margin-top: 10px">
<div class="form-inline mt-3">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">path</span>
<input
@ -18,10 +18,12 @@
</button>
</div>
<div ng-show="$ctrl[$ctrl.formName].name.$invalid">
<div class="small">
<div class="small text-muted">
<div ng-messages="$ctrl[$ctrl.formName].name.$error" class="mt-1">
<p ng-message="required"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Path is required. </p>
<p ng-message="pattern"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> File path must include yaml, yml, json, or hcl extension </p>
<p class="vertical-center" ng-message="required"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Path is required. </p>
<p class="vertical-center" ng-message="pattern">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> File path must include yaml, yml, json, or hcl extension
</p>
</div>
</div>
</div>

View File

@ -1,11 +1,15 @@
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Additional paths</label>
<span class="label label-default interactive" style="margin-left: 10px" ng-click="$ctrl.add()">
<pr-icon icon="'plus'" size="'sm'" mode="'alt'" feather="true"></pr-icon> add file
</span>
<div class="col-sm-12 p-0">
<div class="col-sm-3 col-lg-2">
<label class="control-label text-left">Additional paths</label>
</div>
<div class="col-sm-9 pt-1">
<span class="label label-default interactive vertical-center" ng-click="$ctrl.add()">
<pr-icon icon="'plus'" size="'sm'" mode="'alt'" feather="true"></pr-icon> <span>add file</span>
</span>
</div>
</div>
<div class="col-sm-12 form-inline" style="margin-top: 10px">
<div class="col-sm-12 form-inline">
<git-form-additional-file-item
ng-repeat="variable in $ctrl.model.AdditionalFiles track by $index"
variable="variable"

View File

@ -1,12 +1,13 @@
<div class="form-group">
<div class="col-sm-12">
<por-switch-field
label-class="'col-sm-2'"
checked="$ctrl.model.RepositoryAuthentication"
label="'Authentication'"
label-class="'col-sm-3 col-lg-2'"
name="'authSwitch'"
on-change="($ctrl.onChangeAuth)"
data-cy="'component-gitAuthToggle'"
switch-values="{on:'Yes',off:'No'}"
></por-switch-field>
</div>
</div>

View File

@ -1,14 +1,21 @@
<ng-form name="autoUpdateForm">
<div class="form-group">
<div class="col-sm-12">
<por-switch-field name="'autoUpdate'" checked="$ctrl.model.RepositoryAutomaticUpdates" label="'Automatic Updates'" on-change="($ctrl.onChangeAutoUpdate)"></por-switch-field>
<por-switch-field
name="'autoUpdate'"
checked="$ctrl.model.RepositoryAutomaticUpdates"
label="'Automatic Updates'"
label-class="'col-sm-3 col-lg-2'"
on-change="($ctrl.onChangeAutoUpdate)"
switch-values="{on:'Yes',off:'No'}"
></por-switch-field>
</div>
</div>
<div class="small text-warning" style="margin: 5px 0 10px 0" ng-if="$ctrl.model.RepositoryAutomaticUpdates">
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
<div class="small" ng-if="$ctrl.model.RepositoryAutomaticUpdates">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
<span class="text-muted">Any changes to this stack or application made locally in Portainer will be overridden, which may cause service interruption.</span>
</div>
<div class="form-group" ng-if="$ctrl.model.RepositoryAutomaticUpdates">
<div class="form-group mt-2" ng-if="$ctrl.model.RepositoryAutomaticUpdates">
<label for="repository_mechanism" class="col-lg-2 col-sm-3 control-label text-left"> Mechanism </label>
<div class="col-sm-8">
<div class="input-group col-sm-10 input-group-sm">
@ -49,17 +56,20 @@
required
interval-format
/>
</div>
</div>
<div class="form-group col-md-12" ng-show="autoUpdateForm.repository_fetch_interval.$touched && autoUpdateForm.repository_fetch_interval.$invalid">
<div class="small">
<div ng-messages="autoUpdateForm.repository_fetch_interval.$error">
<p ng-message="required"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This field is required.</p>
<p ng-message="invalidIntervalFormat"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Please enter a valid time interval.</p>
<p ng-message="minimumInterval"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Minimum interval is 1m</p>
<div class="help-group">
<div class="form-group col-md-12 pt-1" ng-show="autoUpdateForm.repository_fetch_interval.$touched && autoUpdateForm.repository_fetch_interval.$invalid">
<div class="small text-muted">
<div ng-messages="autoUpdateForm.repository_fetch_interval.$error">
<p ng-message="required"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This field is required.</p>
<p ng-message="invalidIntervalFormat"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Please enter a valid time interval.</p>
<p ng-message="minimumInterval"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Minimum interval is 1m</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-group" ng-if="$ctrl.showForcePullImage && $ctrl.model.RepositoryAutomaticUpdates">
<div class="col-sm-12">
<por-switch-field
@ -67,6 +77,7 @@
feature="$ctrl.limitedFeaturePullImage"
checked="$ctrl.model.ForcePullImage"
label="'Pull latest image'"
label-class="'col-sm-3 col-lg-2'"
on-change="($ctrl.onChangeForcePullImage)"
></por-switch-field>
</div>
@ -79,16 +90,17 @@
feature-id="$ctrl.limitedFeature"
checked="$ctrl.model.RepositoryAutomaticUpdatesForce"
label="'Force Redeployment'"
label-class="'col-sm-3 col-lg-2'"
on-change="($ctrl.onChangeAutoUpdateForce)"
></por-switch-field>
</div>
</div>
<div class="small" style="margin: 5px 0 10px 0" ng-if="$ctrl.model.RepositoryAutomaticUpdates">
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
<div class="small" ng-if="$ctrl.model.RepositoryAutomaticUpdates">
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
<span class="text-muted">When enabled, enforces automatic deployment at each interval or webhook invocation.</span>
</div>
<div class="small" style="margin: 5px 0 10px 0" ng-if="!$ctrl.model.RepositoryAutomaticUpdates">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon>
<div class="small" ng-if="!$ctrl.model.RepositoryAutomaticUpdates">
<pr-icon icon="'info'" mode="'primary'" feather="true"></pr-icon>
<span class="text-muted">When enabled, updates from the git repository will occur automatically at an interval or webhook.</span>
</div>
</ng-form>

View File

@ -19,7 +19,9 @@
ng-pattern="/.+\.(yml|yaml|json|hcl)$/i"
required
/>
<p class="mt-2" ng-show="pathForm.repoPathField.$error.pattern"> <pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Invalid file path </p>
<p class="mt-2 text-muted small vertical-center" ng-show="pathForm.repoPathField.$error.pattern">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Invalid file path
</p>
</div>
</div>
</ng-form>

View File

@ -1,6 +1,10 @@
.boxselector_wrapper {
display: flex;
flex-flow: row wrap;
gap: 10px;
overflow: hidden !important;
margin-bottom: 5px;
margin-top: 5px;
}
@media only screen and (max-width: 700px) {

View File

@ -2,11 +2,11 @@
.box-selector-item {
--selected-item-color: var(--ui-blue-6);
flex: 1;
padding: 5px;
}
.boxselector_wrapper .boxselector_header {
font-size: 14px;
.boxselector_wrapper .boxselector_header,
.box-selector-item .boxselector_header {
font-size: 18px;
margin-bottom: 5px;
font-weight: bold;
user-select: none;
@ -17,22 +17,26 @@
font-weight: normal;
}
.boxselector_wrapper input[type='radio'] {
.boxselector_wrapper input[type='radio'],
.box-selector-item input[type='radio'] {
display: none;
}
.boxselector_wrapper input[type='radio']:not(:disabled) ~ label {
.boxselector_wrapper input[type='radio']:not(:disabled) ~ label,
.box-selector-item input[type='radio']:not(:disabled) ~ label {
cursor: pointer;
background-color: var(--bg-boxselector-wrapper-disabled-color);
text-align: left;
height: 100%;
}
.boxselector_wrapper input[type='radio']:not(:disabled):hover ~ label:hover {
.boxselector_wrapper input[type='radio']:not(:disabled):hover ~ label:hover,
.box-selector-item input[type='radio']:not(:disabled):hover ~ label:hover {
cursor: pointer;
}
.boxselector_wrapper label {
.boxselector_wrapper label,
.box-selector-item label {
font-weight: normal;
font-size: 12px;
display: block;
@ -109,6 +113,7 @@
}
.box-selector-item.limited.business :checked + label {
background-color: initial;
color: initial;
}
@ -126,11 +131,9 @@
.boxselector_icon,
.boxselector_icon img {
height: 48px;
width: 48px;
color: var(--ui-blue-8);
font-size: 48px;
margin-top: 20px;
font-size: 90px;
display: block;
}
.boxselector_header pr-icon {
@ -140,3 +143,17 @@
.boxselector_content {
padding-left: 20px;
}
.boxselector_wrapper input[type='radio']:not(:disabled) ~ label,
.box-selector-item input[type='radio']:not(:disabled) ~ label {
background-color: var(--ui-gray-2);
}
.boxselector_img_container {
line-height: 90px;
margin-bottom: 0;
}
.box-selector-item p {
margin-bottom: 0;
}

View File

@ -7,3 +7,9 @@
.label {
padding: 0;
}
.switchValues {
font-style: normal;
font-weight: 500;
margin-left: 5px;
}

View File

@ -65,10 +65,14 @@ export function SwitchField({
dataCy={dataCy}
/>
{switchValues && checked && (
<span className="ml-2">{switchValues.on}</span>
<span className={`"ml-2" ${styles.switchValues}`}>
{switchValues.on}
</span>
)}
{switchValues && !checked && (
<span className="ml-2">{switchValues.off}</span>
<span className={`"ml-2" ${styles.switchValues}`}>
{switchValues.off}
</span>
)}
</label>
);