1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 13:55:21 +02:00

feat(edge/stacks): sync EE codechanges [EE-498] (#8580)

This commit is contained in:
Chaim Lev-Ari 2023-05-31 01:33:22 +07:00 committed by GitHub
parent 0ec7dfce69
commit 93bf630105
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1572 additions and 424 deletions

View file

@ -1,8 +1,9 @@
import { EditorType } from '@/react/edge/edge-stacks/types';
import { PortainerEndpointTypes } from '@/portainer/models/endpoint/models';
import { getValidEditorTypes } from '@/react/edge/edge-stacks/utils';
import { STACK_NAME_VALIDATION_REGEX } from '@/react/constants';
import { confirmWebEditorDiscard } from '@@/modals/confirm';
import { baseEdgeStackWebhookUrl } from '@/portainer/helpers/webhookHelper';
import { EnvironmentType } from '@/react/portainer/environments/types';
export default class CreateEdgeStackViewController {
/* @ngInject */
@ -27,6 +28,7 @@ export default class CreateEdgeStackViewController {
};
this.EditorType = EditorType;
this.EnvironmentType = EnvironmentType;
this.state = {
Method: 'editor',
@ -36,6 +38,7 @@ export default class CreateEdgeStackViewController {
isEditorDirty: false,
hasKubeEndpoint: false,
endpointTypes: [],
baseWebhookUrl: baseEdgeStackWebhookUrl(),
};
this.edgeGroups = null;
@ -49,8 +52,7 @@ export default class CreateEdgeStackViewController {
this.createStackFromFileUpload = this.createStackFromFileUpload.bind(this);
this.createStackFromGitRepository = this.createStackFromGitRepository.bind(this);
this.onChangeGroups = this.onChangeGroups.bind(this);
this.hasDockerEndpoint = this.hasDockerEndpoint.bind(this);
this.hasKubeEndpoint = this.hasKubeEndpoint.bind(this);
this.hasType = this.hasType.bind(this);
this.onChangeDeploymentType = this.onChangeDeploymentType.bind(this);
}
@ -139,9 +141,11 @@ export default class CreateEdgeStackViewController {
}
checkIfEndpointTypes(groups) {
const edgeGroups = groups.map((id) => this.edgeGroups.find((e) => e.Id === id));
this.state.endpointTypes = edgeGroups.flatMap((group) => group.EndpointTypes);
this.selectValidDeploymentType();
return this.$scope.$evalAsync(() => {
const edgeGroups = groups.map((id) => this.edgeGroups.find((e) => e.Id === id));
this.state.endpointTypes = edgeGroups.flatMap((group) => group.EndpointTypes);
this.selectValidDeploymentType();
});
}
selectValidDeploymentType() {
@ -152,12 +156,8 @@ export default class CreateEdgeStackViewController {
}
}
hasKubeEndpoint() {
return this.state.endpointTypes.includes(PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment);
}
hasDockerEndpoint() {
return this.state.endpointTypes.includes(PortainerEndpointTypes.EdgeAgentOnDockerEnvironment);
hasType(envType) {
return this.state.endpointTypes.includes(envType);
}
validateForm(method) {

View file

@ -39,12 +39,18 @@
</div>
<!-- !name-input -->
<edge-groups-selector value="$ctrl.formValues.Groups" on-change="($ctrl.onChangeGroups)" items="$ctrl.edgeGroups"></edge-groups-selector>
<edge-groups-selector ng-if="$ctrl.formValues.Groups" value="$ctrl.formValues.Groups" on-change="($ctrl.onChangeGroups)"></edge-groups-selector>
<p class="col-sm-12 vertical-center help-block small text-warning" ng-if="$ctrl.formValues.DeploymentType === undefined">
<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.
</p>
<edge-stack-deployment-type-selector
value="$ctrl.formValues.DeploymentType"
has-docker-endpoint="$ctrl.hasDockerEndpoint()"
has-kube-endpoint="$ctrl.hasKubeEndpoint()"
has-docker-endpoint="$ctrl.hasType($ctrl.EnvironmentType.EdgeAgentOnDocker)"
has-kube-endpoint="$ctrl.hasType($ctrl.EnvironmentType.EdgeAgentOnKubernetes)"
has-nomad-endpoint="$ctrl.hasType($ctrl.EnvironmentType.EdgeAgentOnNomad)"
on-change="($ctrl.onChangeDeploymentType)"
></edge-stack-deployment-type-selector>

View file

@ -21,7 +21,14 @@
<file-upload-description> You can upload a Compose file from your computer. </file-upload-description>
</file-upload-form>
<git-form ng-if="$ctrl.state.Method === 'repository'" value="$ctrl.formValues" on-change="($ctrl.onChangeFormValues)"></git-form>
<git-form
ng-if="$ctrl.state.Method === 'repository'"
value="$ctrl.formValues"
on-change="($ctrl.onChangeFormValues)"
base-webhook-url="{{ $ctrl.state.baseWebhookUrl }}"
webhook-id="{{ $ctrl.state.webhookId }}"
docs-links
></git-form>
<!-- template -->
<div ng-if="$ctrl.state.Method === 'template'">

View file

@ -32,4 +32,11 @@
</file-upload-description>
</file-upload-form>
<git-form ng-if="$ctrl.state.Method === 'repository'" deploy-method="kubernetes" value="$ctrl.formValues" on-change="($ctrl.onChangeFormValues)"></git-form>
<git-form
ng-if="$ctrl.state.Method === 'repository'"
deploy-method="kubernetes"
value="$ctrl.formValues"
on-change="($ctrl.onChangeFormValues)"
base-webhook-url="{{ $ctrl.state.baseWebhookUrl }}"
webhook-id="{{ $ctrl.state.webhookId }}"
></git-form>

View file

@ -12,11 +12,14 @@
<div style="padding: 20px">
<edit-edge-stack-form
ng-if="$ctrl.edgeGroups && $ctrl.stack && $ctrl.formValues.content"
edge-groups="$ctrl.edgeGroups"
model="$ctrl.formValues"
action-in-progress="$ctrl.state.actionInProgress"
submit-action="$ctrl.deployStack"
is-editor-dirty="$ctrl.state.isEditorDirty"
edge-stack="$ctrl.stack"
is-submitting="$ctrl.state.actionInProgress"
on-submit="($ctrl.deployStack)"
on-editor-change="($ctrl.onEditorChange)"
file-content="$ctrl.formValues.content"
allow-kube-to-select-compose="$ctrl.allowKubeToSelectCompose"
></edit-edge-stack-form>
</div>
</uib-tab>

View file

@ -1,6 +1,8 @@
import _ from 'lodash-es';
import { getEnvironments } from '@/react/portainer/environments/environment.service';
import { confirmWebEditorDiscard } from '@@/modals/confirm';
import { EnvironmentType } from '@/react/portainer/environments/types';
import { createWebhookId } from '@/portainer/helpers/webhookHelper';
export class EditEdgeStackViewController {
/* @ngInject */
@ -18,56 +20,74 @@ export class EditEdgeStackViewController {
this.state = {
actionInProgress: false,
activeTab: 0,
isEditorDirty: false,
isStackDeployed: false,
};
this.formValues = {
content: '',
};
this.deployStack = this.deployStack.bind(this);
this.deployStackAsync = this.deployStackAsync.bind(this);
this.getPaginatedEndpoints = this.getPaginatedEndpoints.bind(this);
this.getPaginatedEndpointsAsync = this.getPaginatedEndpointsAsync.bind(this);
this.onEditorChange = this.onEditorChange.bind(this);
this.isEditorDirty = this.isEditorDirty.bind(this);
}
async $onInit() {
const { stackId, tab } = this.$state.params;
this.state.activeTab = tab;
try {
const [edgeGroups, model, file] = await Promise.all([this.EdgeGroupService.groups(), this.EdgeStackService.stack(stackId), this.EdgeStackService.stackFile(stackId)]);
this.edgeGroups = edgeGroups;
this.stack = model;
this.stackEndpointIds = this.filterStackEndpoints(model.EdgeGroups, edgeGroups);
this.originalFileContent = file;
this.formValues = {
StackFileContent: file,
EdgeGroups: this.stack.EdgeGroups,
UseManifestNamespaces: this.stack.UseManifestNamespaces,
DeploymentType: this.stack.DeploymentType,
};
this.oldFileContent = this.formValues.StackFileContent;
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to retrieve stack data');
}
return this.$async(async () => {
const { stackId, tab } = this.$state.params;
this.state.activeTab = tab;
try {
const [edgeGroups, model, file] = await Promise.all([this.EdgeGroupService.groups(), this.EdgeStackService.stack(stackId), this.EdgeStackService.stackFile(stackId)]);
this.$window.onbeforeunload = () => {
if (this.formValues.StackFileContent !== this.oldFileContent && this.state.isEditorDirty) {
return '';
this.edgeGroups = edgeGroups;
this.stack = model;
this.stackEndpointIds = this.filterStackEndpoints(model.EdgeGroups, edgeGroups);
this.originalFileContent = file;
this.formValues = {
content: file,
};
const stackEdgeGroups = model.EdgeGroups.map((id) => this.edgeGroups.find((e) => e.Id === id));
const endpointTypes = stackEdgeGroups.flatMap((group) => group.EndpointTypes);
const initiallyContainsKubeEnv = endpointTypes.includes(EnvironmentType.EdgeAgentOnKubernetes);
const isComposeStack = this.stack.DeploymentType === 0;
this.allowKubeToSelectCompose = initiallyContainsKubeEnv && isComposeStack;
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to retrieve stack data');
}
};
this.oldFileContent = this.formValues.StackFileContent;
this.$window.onbeforeunload = () => {
if (this.isEditorDirty()) {
return '';
}
};
});
}
$onDestroy() {
this.state.isEditorDirty = false;
this.$window.onbeforeunload = undefined;
}
async uiCanExit() {
if (
this.formValues.StackFileContent &&
this.formValues.StackFileContent.replace(/(\r\n|\n|\r)/gm, '') !== this.oldFileContent.replace(/(\r\n|\n|\r)/gm, '') &&
this.state.isEditorDirty
) {
if (this.isEditorDirty()) {
return confirmWebEditorDiscard();
}
}
onEditorChange(content) {
this.formValues.content = content;
}
isEditorDirty() {
return !this.state.isStackDeployed && this.formValues.content.replace(/(\r\n|\n|\r)/gm, '') !== this.originalFileContent.replace(/(\r\n|\n|\r)/gm, '');
}
filterStackEndpoints(groupIds, groups) {
return _.flatten(
_.map(groupIds, (Id) => {
@ -77,19 +97,24 @@ export class EditEdgeStackViewController {
);
}
deployStack() {
return this.$async(this.deployStackAsync);
deployStack(values) {
return this.deployStackAsync(values);
}
async deployStackAsync() {
async deployStackAsync(values) {
this.state.actionInProgress = true;
try {
if (this.originalFileContent != this.formValues.StackFileContent || this.formValues.UseManifestNamespaces !== this.stack.UseManifestNamespaces) {
this.formValues.Version = this.stack.Version + 1;
}
await this.EdgeStackService.updateStack(this.stack.Id, this.formValues);
const updateVersion = !!(this.originalFileContent != values.content || values.useManifestNamespaces !== this.stack.UseManifestNamespaces);
await this.EdgeStackService.updateStack(this.stack.Id, {
stackFileContent: values.content,
edgeGroups: values.edgeGroups,
deploymentType: values.deploymentType,
updateVersion,
webhook: values.webhookEnabled ? this.stack.Webhook || createWebhookId() : '',
});
this.Notifications.success('Success', 'Stack successfully deployed');
this.state.isEditorDirty = false;
this.state.isStackDeployed = true;
this.$state.go('edge.stacks');
} catch (err) {
this.Notifications.error('Deployment error', err, 'Unable to deploy stack');