1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-24 15:59:41 +02:00

feat(templates): allow managing git based templates [EE-2600] (#7855)

Co-authored-by: itsconquest <william.conquest@portainer.io>
Co-authored-by: oscarzhou <oscar.zhou@portainer.io>
Co-authored-by: Chaim Lev-Ari <chiptus@users.noreply.github.com>
This commit is contained in:
Oscar Zhou 2023-04-04 12:44:42 +12:00 committed by GitHub
parent 30a2bb0495
commit c650868fe9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 944 additions and 101 deletions

View file

@ -3,6 +3,7 @@ import { AccessControlFormData } from '@/portainer/components/accessControlForm/
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
import { getTemplateVariables, intersectVariables } from '@/react/portainer/custom-templates/components/utils';
import { confirmWebEditorDiscard } from '@@/modals/confirm';
import { getFilePreview } from '@/react/portainer/gitops/gitops.service';
class KubeEditCustomTemplateViewController {
/* @ngInject */
@ -11,11 +12,18 @@ class KubeEditCustomTemplateViewController {
this.isTemplateVariablesEnabled = isBE;
this.formValues = null;
this.formValues = {
Variables: [],
TLSSkipVerify: false,
};
this.state = {
formValidationError: '',
isEditorDirty: false,
isTemplateValid: true,
isEditorReadOnly: false,
templateLoadFailed: false,
templatePreviewFailed: false,
templatePreviewError: '',
};
this.templates = [];
@ -25,6 +33,7 @@ class KubeEditCustomTemplateViewController {
this.onBeforeUnload = this.onBeforeUnload.bind(this);
this.handleChange = this.handleChange.bind(this);
this.onVariablesChange = this.onVariablesChange.bind(this);
this.previewFileFromGitRepository = this.previewFileFromGitRepository.bind(this);
}
getTemplate() {
@ -32,13 +41,25 @@ class KubeEditCustomTemplateViewController {
try {
const { id } = this.$state.params;
const [template, file] = await Promise.all([this.CustomTemplateService.customTemplate(id), this.CustomTemplateService.customTemplateFile(id)]);
template.FileContent = file;
const template = await this.CustomTemplateService.customTemplate(id);
if (template.GitConfig !== null) {
this.state.isEditorReadOnly = true;
}
try {
template.FileContent = await this.CustomTemplateService.customTemplateFile(id, template.GitConfig !== null);
} catch (err) {
this.state.templateLoadFailed = true;
throw err;
}
template.Variables = template.Variables || [];
this.formValues = template;
this.formValues = { ...this.formValues, ...template };
this.parseTemplate(file);
this.parseTemplate(template.FileContent);
this.parseGitConfig(template.GitConfig);
this.oldFileContent = this.formValues.FileContent;
@ -79,6 +100,62 @@ class KubeEditCustomTemplateViewController {
}
}
parseGitConfig(config) {
if (config === null) {
return;
}
let flatConfig = {
RepositoryURL: config.URL,
RepositoryReferenceName: config.ReferenceName,
ComposeFilePathInRepository: config.ConfigFilePath,
RepositoryAuthentication: config.Authentication !== null,
TLSSkipVerify: config.TLSSkipVerify,
};
if (config.Authentication) {
flatConfig = {
...flatConfig,
RepositoryUsername: config.Authentication.Username,
RepositoryPassword: config.Authentication.Password,
};
}
this.formValues = { ...this.formValues, ...flatConfig };
}
previewFileFromGitRepository() {
this.state.templatePreviewFailed = false;
this.state.templatePreviewError = '';
let creds = {};
if (this.formValues.RepositoryAuthentication) {
creds = {
username: this.formValues.RepositoryUsername,
password: this.formValues.RepositoryPassword,
};
}
const payload = {
repository: this.formValues.RepositoryURL,
targetFile: this.formValues.ComposeFilePathInRepository,
tlsSkipVerify: this.formValues.TLSSkipVerify,
...creds,
};
this.$async(async () => {
try {
this.formValues.FileContent = await getFilePreview(payload);
this.state.isEditorDirty = true;
// check if the template contains mustache template symbol
this.parseTemplate(this.formValues.FileContent);
} catch (err) {
this.state.templatePreviewError = err.message;
this.state.templatePreviewFailed = true;
}
});
}
validateForm() {
this.state.formValidationError = '';

View file

@ -7,6 +7,22 @@
<form class="form-horizontal" name="$ctrl.form">
<custom-template-common-fields form-values="$ctrl.formValues"></custom-template-common-fields>
<git-form value="$ctrl.formValues" on-change="($ctrl.handleChange)" ng-if="$ctrl.formValues.GitConfig"></git-form>
<div class="form-group">
<div class="col-sm-12"
><button type="button" class="btn btn-sm btn-light !ml-0" ng-if="$ctrl.formValues.GitConfig" ng-click="$ctrl.previewFileFromGitRepository()">
<pr-icon icon="'refresh-cw'" feather="true"></pr-icon>Reload custom template</button
>
</div>
<div class="col-sm-12" ng-if="$ctrl.state.templatePreviewFailed">
<p class="small vertical-center text-danger mt-5">
<pr-icon icon="'alert-triangle'" mode="'danger'" size="'md'" feather="true"></pr-icon>
Custom template could not be loaded, {{ $ctrl.state.templatePreviewError }}.</p
>
</div>
</div>
<web-editor-form
identifier="template-editor"
value="$ctrl.formValues.FileContent"
@ -14,6 +30,7 @@
ng-required="true"
yml="true"
placeholder="Define or paste the content of your manifest file here"
read-only="$ctrl.state.isEditorReadOnly"
>
<editor-description>
<p>Templates allow deploying any kind of Kubernetes resource (Deployment, Secret, ConfigMap...)</p>
@ -31,7 +48,11 @@
is-variables-names-from-parent="true"
></custom-templates-variables-definition-field>
<por-access-control-form form-data="$ctrl.formValues.AccessControlData" resource-control="$ctrl.formValues.ResourceControl"></por-access-control-form>
<por-access-control-form
form-data="$ctrl.formValues.AccessControlData"
resource-control="$ctrl.formValues.ResourceControl"
ng-if="$ctrl.formValues.AccessControlData"
></por-access-control-form>
<div class="col-sm-12 form-section-title"> Actions </div>
<div class="form-group">