mirror of https://github.com/portainer/portainer
fix(edge stacks): allow viewing existing kompose stacks [EE-4967] (#8405)
Co-authored-by: testa113 <testa113> Co-authored-by: Matt Hook <hookenz@gmail.com>pull/8422/head
parent
53eb5aa1ee
commit
8574dd2371
|
@ -9,13 +9,19 @@
|
||||||
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> There are no available deployment types when there is more than one type of environment in your edge group
|
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> There are no available deployment types when there is more than one type of environment in your edge group
|
||||||
selection (e.g. Kubernetes and Docker environments). Please select edge groups that have environments of the same type.
|
selection (e.g. Kubernetes and Docker environments). Please select edge groups that have environments of the same type.
|
||||||
</p>
|
</p>
|
||||||
|
<p class="col-sm-12 vertical-center help-block small text-warning" ng-if="$ctrl.model.DeploymentType === $ctrl.EditorType.Compose && $ctrl.hasKubeEndpoint()">
|
||||||
|
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Edge groups with kubernetes environments no longer support compose deployment types in Portainer. Please select
|
||||||
|
edge groups that only have docker environments when using compose deployment types.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<edge-stack-deployment-type-selector
|
<edge-stack-deployment-type-selector
|
||||||
|
allow-kube-to-select-compose="$ctrl.allowKubeToSelectCompose"
|
||||||
value="$ctrl.model.DeploymentType"
|
value="$ctrl.model.DeploymentType"
|
||||||
has-docker-endpoint="$ctrl.hasDockerEndpoint()"
|
has-docker-endpoint="$ctrl.hasDockerEndpoint()"
|
||||||
has-kube-endpoint="$ctrl.hasKubeEndpoint()"
|
has-kube-endpoint="$ctrl.hasKubeEndpoint()"
|
||||||
on-change="($ctrl.onChangeDeploymentType)"
|
on-change="($ctrl.onChangeDeploymentType)"
|
||||||
|
read-only="$ctrl.state.readOnlyCompose"
|
||||||
></edge-stack-deployment-type-selector>
|
></edge-stack-deployment-type-selector>
|
||||||
|
|
||||||
<div class="flex gap-1 text-muted small" ng-show="!$ctrl.model.DeploymentType && $ctrl.hasKubeEndpoint()">
|
<div class="flex gap-1 text-muted small" ng-show="!$ctrl.model.DeploymentType && $ctrl.hasKubeEndpoint()">
|
||||||
|
@ -89,8 +95,8 @@
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm !ml-0"
|
||||||
ng-disabled="$ctrl.actionInProgress || !$ctrl.isFormValid()"
|
ng-disabled="$ctrl.actionInProgress || !$ctrl.isFormValid() || (!$ctrl.model.DeploymentType && $ctrl.hasKubeEndpoint())"
|
||||||
ng-click="$ctrl.submitAction()"
|
ng-click="$ctrl.submitAction()"
|
||||||
button-spinner="$ctrl.actionInProgress"
|
button-spinner="$ctrl.actionInProgress"
|
||||||
>
|
>
|
||||||
|
|
|
@ -7,6 +7,7 @@ export class EditEdgeStackFormController {
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.state = {
|
this.state = {
|
||||||
endpointTypes: [],
|
endpointTypes: [],
|
||||||
|
readOnlyCompose: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fileContents = {
|
this.fileContents = {
|
||||||
|
@ -26,6 +27,7 @@ export class EditEdgeStackFormController {
|
||||||
this.removeLineBreaks = this.removeLineBreaks.bind(this);
|
this.removeLineBreaks = this.removeLineBreaks.bind(this);
|
||||||
this.onChangeFileContent = this.onChangeFileContent.bind(this);
|
this.onChangeFileContent = this.onChangeFileContent.bind(this);
|
||||||
this.onChangeUseManifestNamespaces = this.onChangeUseManifestNamespaces.bind(this);
|
this.onChangeUseManifestNamespaces = this.onChangeUseManifestNamespaces.bind(this);
|
||||||
|
this.selectValidDeploymentType = this.selectValidDeploymentType.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeUseManifestNamespaces(value) {
|
onChangeUseManifestNamespaces(value) {
|
||||||
|
@ -45,8 +47,9 @@ export class EditEdgeStackFormController {
|
||||||
onChangeGroups(groups) {
|
onChangeGroups(groups) {
|
||||||
return this.$scope.$evalAsync(() => {
|
return this.$scope.$evalAsync(() => {
|
||||||
this.model.EdgeGroups = groups;
|
this.model.EdgeGroups = groups;
|
||||||
|
this.setEnvironmentTypesInSelection(groups);
|
||||||
this.checkEndpointTypes(groups);
|
this.selectValidDeploymentType();
|
||||||
|
this.state.readOnlyCompose = this.hasKubeEndpoint();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +57,13 @@ export class EditEdgeStackFormController {
|
||||||
return this.model.EdgeGroups.length && this.model.StackFileContent && this.validateEndpointsForDeployment();
|
return this.model.EdgeGroups.length && this.model.StackFileContent && this.validateEndpointsForDeployment();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEndpointTypes(groups) {
|
setEnvironmentTypesInSelection(groups) {
|
||||||
const edgeGroups = groups.map((id) => this.edgeGroups.find((e) => e.Id === id));
|
const edgeGroups = groups.map((id) => this.edgeGroups.find((e) => e.Id === id));
|
||||||
this.state.endpointTypes = edgeGroups.flatMap((group) => group.EndpointTypes);
|
this.state.endpointTypes = edgeGroups.flatMap((group) => group.EndpointTypes);
|
||||||
this.selectValidDeploymentType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectValidDeploymentType() {
|
selectValidDeploymentType() {
|
||||||
const validTypes = getValidEditorTypes(this.state.endpointTypes);
|
const validTypes = getValidEditorTypes(this.state.endpointTypes, this.allowKubeToSelectCompose);
|
||||||
|
|
||||||
if (!validTypes.includes(this.model.DeploymentType)) {
|
if (!validTypes.includes(this.model.DeploymentType)) {
|
||||||
this.onChangeDeploymentType(validTypes[0]);
|
this.onChangeDeploymentType(validTypes[0]);
|
||||||
|
@ -101,7 +103,14 @@ export class EditEdgeStackFormController {
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
this.checkEndpointTypes(this.model.EdgeGroups);
|
this.setEnvironmentTypesInSelection(this.model.EdgeGroups);
|
||||||
this.fileContents[this.model.DeploymentType] = this.model.StackFileContent;
|
this.fileContents[this.model.DeploymentType] = this.model.StackFileContent;
|
||||||
|
|
||||||
|
// allow kube to view compose if it's an existing kube compose stack
|
||||||
|
const initiallyContainsKubeEnv = this.hasKubeEndpoint();
|
||||||
|
const isComposeStack = this.model.DeploymentType === 0;
|
||||||
|
this.allowKubeToSelectCompose = initiallyContainsKubeEnv && isComposeStack;
|
||||||
|
this.state.readOnlyCompose = this.allowKubeToSelectCompose;
|
||||||
|
this.selectValidDeploymentType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,5 +52,6 @@ export const componentsModule = angular
|
||||||
'onChange',
|
'onChange',
|
||||||
'hasDockerEndpoint',
|
'hasDockerEndpoint',
|
||||||
'hasKubeEndpoint',
|
'hasKubeEndpoint',
|
||||||
|
'allowKubeToSelectCompose',
|
||||||
])
|
])
|
||||||
).name;
|
).name;
|
||||||
|
|
|
@ -35,8 +35,19 @@
|
||||||
ng-if="ctrl.stack.IsComposeFormat"
|
ng-if="ctrl.stack.IsComposeFormat"
|
||||||
title="'View application'"
|
title="'View application'"
|
||||||
breadcrumbs="[
|
breadcrumbs="[
|
||||||
|
{ label:'Namespaces', link:'kubernetes.resourcePools' },
|
||||||
|
{
|
||||||
|
label:ctrl.application.ResourcePool,
|
||||||
|
link: 'kubernetes.resourcePools.resourcePool',
|
||||||
|
linkParams:{ id: ctrl.application.ResourcePool }
|
||||||
|
},
|
||||||
{ label:'Applications', link:'kubernetes.applications' },
|
{ label:'Applications', link:'kubernetes.applications' },
|
||||||
'View application'
|
{
|
||||||
|
label:ctrl.application.Name,
|
||||||
|
link: 'kubernetes.applications.application',
|
||||||
|
linkParams:{ name: ctrl.application.Name, namespace: ctrl.application.ResourcePool }
|
||||||
|
},
|
||||||
|
'View',
|
||||||
]"
|
]"
|
||||||
reload="true"
|
reload="true"
|
||||||
>
|
>
|
||||||
|
|
|
@ -5,6 +5,10 @@ angular.module('portainer.app').controller('CodeEditorController', function Code
|
||||||
if (value && value.currentValue && ctrl.editor && ctrl.editor.getValue() !== value.currentValue) {
|
if (value && value.currentValue && ctrl.editor && ctrl.editor.getValue() !== value.currentValue) {
|
||||||
ctrl.editor.setValue(value.currentValue);
|
ctrl.editor.setValue(value.currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctrl.editor) {
|
||||||
|
ctrl.editor.setOption('readOnly', ctrl.readOnly);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$onInit = function () {
|
this.$onInit = function () {
|
||||||
|
|
|
@ -12,6 +12,7 @@ interface Props {
|
||||||
onChange(value: number): void;
|
onChange(value: number): void;
|
||||||
hasDockerEndpoint: boolean;
|
hasDockerEndpoint: boolean;
|
||||||
hasKubeEndpoint: boolean;
|
hasKubeEndpoint: boolean;
|
||||||
|
allowKubeToSelectCompose?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EdgeStackDeploymentTypeSelector({
|
export function EdgeStackDeploymentTypeSelector({
|
||||||
|
@ -19,12 +20,13 @@ export function EdgeStackDeploymentTypeSelector({
|
||||||
onChange,
|
onChange,
|
||||||
hasDockerEndpoint,
|
hasDockerEndpoint,
|
||||||
hasKubeEndpoint,
|
hasKubeEndpoint,
|
||||||
|
allowKubeToSelectCompose,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const deploymentOptions: BoxSelectorOption<number>[] = [
|
const deploymentOptions: BoxSelectorOption<number>[] = [
|
||||||
{
|
{
|
||||||
...compose,
|
...compose,
|
||||||
value: EditorType.Compose,
|
value: EditorType.Compose,
|
||||||
disabled: () => hasKubeEndpoint,
|
disabled: () => (allowKubeToSelectCompose ? false : hasKubeEndpoint),
|
||||||
tooltip: () =>
|
tooltip: () =>
|
||||||
hasKubeEndpoint
|
hasKubeEndpoint
|
||||||
? 'Cannot use this option with Edge Kubernetes environments'
|
? 'Cannot use this option with Edge Kubernetes environments'
|
||||||
|
|
|
@ -4,10 +4,15 @@ import { EnvironmentType } from '@/react/portainer/environments/types';
|
||||||
|
|
||||||
import { EditorType } from './types';
|
import { EditorType } from './types';
|
||||||
|
|
||||||
export function getValidEditorTypes(endpointTypes: EnvironmentType[]) {
|
export function getValidEditorTypes(
|
||||||
|
endpointTypes: EnvironmentType[],
|
||||||
|
allowKubeToSelectCompose?: boolean
|
||||||
|
) {
|
||||||
const right: Partial<Record<EnvironmentType, EditorType[]>> = {
|
const right: Partial<Record<EnvironmentType, EditorType[]>> = {
|
||||||
[EnvironmentType.EdgeAgentOnDocker]: [EditorType.Compose],
|
[EnvironmentType.EdgeAgentOnDocker]: [EditorType.Compose],
|
||||||
[EnvironmentType.EdgeAgentOnKubernetes]: [EditorType.Kubernetes],
|
[EnvironmentType.EdgeAgentOnKubernetes]: allowKubeToSelectCompose
|
||||||
|
? [EditorType.Kubernetes, EditorType.Compose]
|
||||||
|
: [EditorType.Kubernetes],
|
||||||
};
|
};
|
||||||
|
|
||||||
return endpointTypes.length
|
return endpointTypes.length
|
||||||
|
|
Loading…
Reference in New Issue