mirror of
https://github.com/portainer/portainer.git
synced 2025-08-04 21:35:23 +02:00
feat(stacks): redeploy git stack [EE-161] (#5139)
* feat(git): save git config when creating stack (#5048) * feat(git): save git config when creating stack * chore(fs): test fileExists * fix(git): fix tests to use CloneRepository * refactor(git): move options to new object * feat(stacks): redeploy git stack api (#5112) * feat(stacks): redeploy git stacks form [EE-666] * feat(stack): show loading after confirmation * fix(stacks): show same size description * fix(stacks): reload state when deployed * feat(stacks): set stopped stacks status to activate when updating * feat(stacks): backup stack folder before cloning * feat(stacks): don't accept prune and env on update git Co-authored-by: Chaim Lev-Ari <chiptus@users.noreply.github.com> Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com>
This commit is contained in:
parent
296ecc5960
commit
0b93714de4
54 changed files with 795 additions and 381 deletions
|
@ -1023,3 +1023,8 @@ json-tree .branch-preview {
|
|||
overflow-y: auto;
|
||||
}
|
||||
/* !uib-typeahead override */
|
||||
|
||||
.my-8 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
|
|
@ -136,78 +136,7 @@
|
|||
</div>
|
||||
<!-- !upload -->
|
||||
<!-- repository -->
|
||||
<div ng-show="$ctrl.state.Method === 'repository'">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Git repository
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can use the URL of a git repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_url" class="col-sm-2 control-label text-left">Repository URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.formValues.RepositoryURL"
|
||||
id="stack_repository_url"
|
||||
placeholder="https://github.com/portainer/portainer-compose"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Specify a reference of the repository using the following syntax: branches with
|
||||
<code>refs/heads/branch_name</code> or tags with <code>refs/tags/tag_name</code>. If not specified, will use the default <code>HEAD</code> reference normally the
|
||||
<code>master</code> branch.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_url" class="col-sm-2 control-label text-left">Repository reference</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.formValues.RepositoryReferenceName" id="stack_repository_reference_name" placeholder="refs/heads/master" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Indicate the path to the Compose file from the root of your repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_path" class="col-sm-2 control-label text-left">Compose path</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.formValues.ComposeFilePathInRepository" id="stack_repository_path" placeholder="docker-compose.yml" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">
|
||||
Authentication
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="$ctrl.formValues.RepositoryAuthentication" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="$ctrl.formValues.RepositoryAuthentication">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
If your git account has 2FA enabled, you may receive an
|
||||
<code>authentication required</code> error when deploying your stack. In this case, you will need to provide a personal-access token instead of your password.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group" ng-if="$ctrl.formValues.RepositoryAuthentication">
|
||||
<label for="repository_username" class="col-sm-1 control-label text-left">Username</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.formValues.RepositoryUsername" name="repository_username" placeholder="myGitUser" />
|
||||
</div>
|
||||
<label for="repository_password" class="col-sm-1 control-label text-left">
|
||||
Password
|
||||
</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input type="password" class="form-control" ng-model="$ctrl.formValues.RepositoryPassword" name="repository_password" placeholder="myPassword" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<git-form ng-show="$ctrl.state.Method === 'repository'" model="$ctrl.formValues" on-change="($ctrl.onChangeFormValues)"></git-form>
|
||||
<!-- !repository -->
|
||||
<!-- template -->
|
||||
<div ng-show="$ctrl.state.Method === 'template'">
|
||||
|
|
|
@ -40,6 +40,7 @@ export class CreateEdgeStackViewController {
|
|||
this.onChangeTemplate = this.onChangeTemplate.bind(this);
|
||||
this.onChangeTemplateAsync = this.onChangeTemplateAsync.bind(this);
|
||||
this.onChangeMethod = this.onChangeMethod.bind(this);
|
||||
this.onChangeFormValues = this.onChangeFormValues.bind(this);
|
||||
}
|
||||
|
||||
async uiCanExit() {
|
||||
|
@ -161,6 +162,10 @@ export class CreateEdgeStackViewController {
|
|||
return this.EdgeStackService.createStackFromGitRepository(name, repositoryOptions, this.formValues.Groups);
|
||||
}
|
||||
|
||||
onChangeFormValues(values) {
|
||||
this.formValues = values;
|
||||
}
|
||||
|
||||
editorUpdate(cm) {
|
||||
this.formValues.StackFileContent = cm.getValue();
|
||||
this.state.isEditorDirty = true;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import _ from 'lodash-es';
|
||||
|
||||
import componentsModule from './components';
|
||||
|
||||
async function initAuthentication(authManager, Authentication, $rootScope, $state) {
|
||||
authManager.checkAuthOnRefresh();
|
||||
// The unauthenticated event is broadcasted by the jwtInterceptor when
|
||||
|
@ -15,7 +17,7 @@ async function initAuthentication(authManager, Authentication, $rootScope, $stat
|
|||
return await Authentication.init();
|
||||
}
|
||||
|
||||
angular.module('portainer.app', ['portainer.oauth']).config([
|
||||
angular.module('portainer.app', ['portainer.oauth', componentsModule]).config([
|
||||
'$stateRegistryProvider',
|
||||
function ($stateRegistryProvider) {
|
||||
'use strict';
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
class GitFormComposeAuthFieldsetController {
|
||||
/* @ngInject */
|
||||
constructor() {
|
||||
this.onChangeField = this.onChangeField.bind(this);
|
||||
this.onChangeAuth = this.onChangeField('RepositoryAuthentication');
|
||||
this.onChangeUsername = this.onChangeField('RepositoryUsername');
|
||||
this.onChangePassword = this.onChangeField('RepositoryPassword');
|
||||
}
|
||||
|
||||
onChangeField(field) {
|
||||
return (value) => {
|
||||
this.onChange({
|
||||
...this.model,
|
||||
[field]: value,
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default GitFormComposeAuthFieldsetController;
|
|
@ -0,0 +1,39 @@
|
|||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<por-switch-field ng-model="$ctrl.model.RepositoryAuthentication" label="Authentication" on-change="($ctrl.onChangeAuth)"></por-switch-field>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="$ctrl.model.RepositoryAuthentication">
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
If your git account has 2FA enabled, you may receive an <code>authentication required</code> error when deploying your stack. In this case, you will need to provide a
|
||||
personal-access token instead of your password.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="repository_username" class="col-sm-1 control-label text-left">Username</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.model.RepositoryUsername"
|
||||
name="repository_username"
|
||||
placeholder="myGitUser"
|
||||
ng-change="$ctrl.onChangeUsername($ctrl.model.RepositoryUsername)"
|
||||
/>
|
||||
</div>
|
||||
<label for="repository_password" class="col-sm-1 control-label text-left">
|
||||
Password
|
||||
</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.model.RepositoryPassword"
|
||||
name="repository_password"
|
||||
placeholder="myPassword"
|
||||
ng-change="$ctrl.onChangePassword($ctrl.model.RepositoryPassword)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
import controller from './git-form-auth-fieldset.controller.js';
|
||||
|
||||
export const gitFormAuthFieldset = {
|
||||
templateUrl: './git-form-auth-fieldset.html',
|
||||
controller,
|
||||
bindings: {
|
||||
model: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Indicate the path to the Compose file from the root of your repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_path" class="col-sm-2 control-label text-left">Compose path</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.value" ng-change="$ctrl.onChange($ctrl.value)" id="stack_repository_path" placeholder="docker-compose.yml" />
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
export const gitFormComposePathField = {
|
||||
templateUrl: './git-form-compose-path-field.html',
|
||||
bindings: {
|
||||
value: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Specify a reference of the repository using the following syntax: branches with <code>refs/heads/branch_name</code> or tags with <code>refs/tags/tag_name</code>. If not
|
||||
specified, will use the default <code>HEAD</code> reference normally the <code>master</code> branch.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_reference_name" class="col-sm-2 control-label text-left">Repository reference</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.value" id="stack_repository_reference_name" placeholder="refs/heads/master" ng-change="$ctrl.onChange($ctrl.value)" />
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
export const gitFormRefField = {
|
||||
templateUrl: './git-form-ref-field.html',
|
||||
bindings: {
|
||||
value: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can use the URL of a git repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_url" class="col-sm-2 control-label text-left">Repository URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.value"
|
||||
ng-change="$ctrl.onChange($ctrl.value)"
|
||||
id="stack_repository_url"
|
||||
placeholder="https://github.com/portainer/portainer-compose"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
export const gitFormUrlField = {
|
||||
templateUrl: './git-form-url-field.html',
|
||||
bindings: {
|
||||
value: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
export default class GitFormController {
|
||||
/* @ngInject */
|
||||
constructor() {
|
||||
this.onChangeField = this.onChangeField.bind(this);
|
||||
this.onChangeURL = this.onChangeField('RepositoryURL');
|
||||
this.onChangeRefName = this.onChangeField('RepositoryReferenceName');
|
||||
this.onChangeComposePath = this.onChangeField('ComposeFilePathInRepository');
|
||||
}
|
||||
|
||||
onChangeField(field) {
|
||||
return (value) => {
|
||||
this.onChange({
|
||||
...this.model,
|
||||
[field]: value,
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
9
app/portainer/components/forms/git-form/git-form.html
Normal file
9
app/portainer/components/forms/git-form/git-form.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div>
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Git repository
|
||||
</div>
|
||||
<git-form-url-field value="$ctrl.model.RepositoryURL" on-change="($ctrl.onChangeURL)"></git-form-url-field>
|
||||
<git-form-ref-field value="$ctrl.model.RepositoryReferenceName" on-change="($ctrl.onChangeRefName)"></git-form-ref-field>
|
||||
<git-form-compose-path-field value="$ctrl.model.ComposeFilePathInRepository" on-change="($ctrl.onChangeComposePath)"></git-form-compose-path-field>
|
||||
<git-form-auth-fieldset model="$ctrl.model" on-change="($ctrl.onChange)"></git-form-auth-fieldset>
|
||||
</div>
|
10
app/portainer/components/forms/git-form/git-form.js
Normal file
10
app/portainer/components/forms/git-form/git-form.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import controller from './git-form.controller.js';
|
||||
|
||||
export const gitForm = {
|
||||
templateUrl: './git-form.html',
|
||||
controller,
|
||||
bindings: {
|
||||
model: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
15
app/portainer/components/forms/git-form/index.js
Normal file
15
app/portainer/components/forms/git-form/index.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { gitForm } from './git-form';
|
||||
import { gitFormAuthFieldset } from './git-form-auth-fieldset';
|
||||
import { gitFormComposePathField } from './git-form-compose-path-field';
|
||||
import { gitFormRefField } from './git-form-ref-field';
|
||||
import { gitFormUrlField } from './git-form-url-field';
|
||||
|
||||
export default angular
|
||||
.module('portainer.app.components.forms.git', [])
|
||||
.component('gitFormComposePathField', gitFormComposePathField)
|
||||
.component('gitFormRefField', gitFormRefField)
|
||||
.component('gitForm', gitForm)
|
||||
.component('gitFormUrlField', gitFormUrlField)
|
||||
.component('gitFormAuthFieldset', gitFormAuthFieldset).name;
|
|
@ -0,0 +1,13 @@
|
|||
import angular from 'angular';
|
||||
import controller from './stack-redeploy-git-form.controller.js';
|
||||
|
||||
export const stackRedeployGitForm = {
|
||||
templateUrl: './stack-redeploy-git-form.html',
|
||||
controller,
|
||||
bindings: {
|
||||
model: '<',
|
||||
stack: '<',
|
||||
},
|
||||
};
|
||||
|
||||
angular.module('portainer.app').component('stackRedeployGitForm', stackRedeployGitForm);
|
|
@ -0,0 +1,75 @@
|
|||
class StackRedeployGitFormController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, StackService, ModalService, Notifications) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.StackService = StackService;
|
||||
this.ModalService = ModalService;
|
||||
this.Notifications = Notifications;
|
||||
|
||||
this.state = {
|
||||
inProgress: false,
|
||||
};
|
||||
|
||||
this.formValues = {
|
||||
RefName: '',
|
||||
RepositoryAuthentication: false,
|
||||
RepositoryUsername: '',
|
||||
RepositoryPassword: '',
|
||||
};
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onChangeRef = this.onChangeRef.bind(this);
|
||||
}
|
||||
|
||||
onChangeRef(value) {
|
||||
this.onChange({ RefName: value });
|
||||
}
|
||||
|
||||
onChange(values) {
|
||||
this.formValues = {
|
||||
...this.formValues,
|
||||
...values,
|
||||
};
|
||||
}
|
||||
|
||||
async submit() {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
const confirmed = await this.ModalService.confirmAsync({
|
||||
title: 'Are you sure?',
|
||||
message: 'Any changes to this stack made locally in Portainer will be overridden by the definition in git and may cause a service interruption. Do you wish to continue',
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: 'Update',
|
||||
className: 'btn-warning',
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state.inProgress = true;
|
||||
|
||||
await this.StackService.updateGit(this.stack.Id, this.stack.EndpointId, [], false, this.formValues);
|
||||
|
||||
await this.$state.reload();
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Failed redeploying stack');
|
||||
} finally {
|
||||
this.state.inProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isSubmitButtonDisabled() {
|
||||
return this.state.inProgress;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.formValues.RefName = this.model.ReferenceName;
|
||||
}
|
||||
}
|
||||
|
||||
export default StackRedeployGitFormController;
|
|
@ -0,0 +1,30 @@
|
|||
<form name="$ctrl.redeployGitForm" class="form-horizontal my-8">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Redeploy from git repository
|
||||
</div>
|
||||
<div class="text-muted small form-group">
|
||||
<div class="col-sm-12">
|
||||
<p>
|
||||
This stack was deployed from the git repository <code>{{ $ctrl.model.URL }}</code>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
Update <code>{{ $ctrl.model.ConfigFilePath }}</code> in git and pull from here to update the stack.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<git-form-ref-field value="$ctrl.formValues.RefName" on-change="($ctrl.onChangeRef)"></git-form-ref-field>
|
||||
<git-form-auth-fieldset model="$ctrl.formValues" on-change="($ctrl.onChange)"></git-form-auth-fieldset>
|
||||
|
||||
<button
|
||||
class="btn btn-sm btn-primary"
|
||||
ng-click="$ctrl.submit()"
|
||||
ng-disabled="$ctrl.isSubmitButtonDisabled()"
|
||||
style="margin-top: 7px; margin-left: 0;"
|
||||
button-spinner="$ctrl.state.inProgress"
|
||||
>
|
||||
<span ng-hide="$ctrl.state.inProgress"> <i class="fa fa-sync space-right" aria-hidden="true"></i> Pull and redeploy </span>
|
||||
<span ng-show="$ctrl.state.inProgress">In progress...</span>
|
||||
</button>
|
||||
</form>
|
5
app/portainer/components/index.js
Normal file
5
app/portainer/components/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import gitFormModule from './forms/git-form';
|
||||
|
||||
export default angular.module('portainer.app.components', [gitFormModule]).name;
|
|
@ -15,11 +15,11 @@ export function StackViewModel(data) {
|
|||
this.CreatedBy = data.CreatedBy;
|
||||
this.UpdateDate = data.UpdateDate;
|
||||
this.UpdatedBy = data.UpdatedBy;
|
||||
|
||||
this.Regular = true;
|
||||
this.External = false;
|
||||
this.Orphaned = false;
|
||||
this.Checked = false;
|
||||
this.GitConfig = data.GitConfig;
|
||||
}
|
||||
|
||||
export function ExternalStackViewModel(name, type, creationDate) {
|
||||
|
|
|
@ -18,6 +18,7 @@ angular.module('portainer.app').factory('Stack', [
|
|||
migrate: { method: 'POST', params: { id: '@id', action: 'migrate', endpointId: '@endpointId' }, ignoreLoadingBar: true },
|
||||
start: { method: 'POST', params: { id: '@id', action: 'start' } },
|
||||
stop: { method: 'POST', params: { id: '@id', action: 'stop' } },
|
||||
updateGit: { method: 'PUT', params: { action: 'git' } },
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
|
@ -13,7 +13,9 @@ angular.module('portainer.app').factory('StackService', [
|
|||
'EndpointProvider',
|
||||
function StackServiceFactory($q, $async, Stack, FileUploadService, StackHelper, ServiceService, ContainerService, SwarmService, EndpointProvider) {
|
||||
'use strict';
|
||||
var service = {};
|
||||
var service = {
|
||||
updateGit,
|
||||
};
|
||||
|
||||
service.stack = function (id) {
|
||||
var deferred = $q.defer();
|
||||
|
@ -394,6 +396,20 @@ angular.module('portainer.app').factory('StackService', [
|
|||
return Stack.stop({ id }).$promise;
|
||||
}
|
||||
|
||||
function updateGit(id, endpointId, env, prune, gitConfig) {
|
||||
return Stack.updateGit(
|
||||
{ endpointId, id },
|
||||
{
|
||||
env,
|
||||
prune,
|
||||
RepositoryReferenceName: gitConfig.RefName,
|
||||
RepositoryAuthentication: gitConfig.RepositoryAuthentication,
|
||||
RepositoryUsername: gitConfig.RepositoryUsername,
|
||||
RepositoryPassword: gitConfig.RepositoryPassword,
|
||||
}
|
||||
).$promise;
|
||||
}
|
||||
|
||||
return service;
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -103,84 +103,7 @@
|
|||
</div>
|
||||
<!-- !upload -->
|
||||
<!-- repository -->
|
||||
<div ng-show="$ctrl.state.Method === 'repository'">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Git repository
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can use the URL of a git repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="template_repository_url" class="col-sm-2 control-label text-left">Repository URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.formValues.RepositoryURL"
|
||||
id="template_repository_url"
|
||||
placeholder="https://github.com/portainer/portainer-compose"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Specify a reference of the repository using the following syntax: branches with
|
||||
<code>refs/heads/branch_name</code> or tags with <code>refs/tags/tag_name</code>. If not specified, will use the default <code>HEAD</code> reference normally the
|
||||
<code>master</code> branch.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="template_repository_url" class="col-sm-2 control-label text-left">Repository reference</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.formValues.RepositoryReferenceName"
|
||||
id="template_repository_reference_name"
|
||||
placeholder="refs/heads/master"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Indicate the path to the Compose file from the root of your repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="template_repository_path" class="col-sm-2 control-label text-left">Compose path</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.formValues.ComposeFilePathInRepository" id="template_repository_path" placeholder="docker-compose.yml" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">
|
||||
Authentication
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="$ctrl.formValues.RepositoryAuthentication" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="$ctrl.formValues.RepositoryAuthentication">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
If your git account has 2FA enabled, you may receive an
|
||||
<code>authentication required</code> error when creating your template. In this case, you will need to provide a personal-access token instead of your password.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group" ng-if="$ctrl.formValues.RepositoryAuthentication">
|
||||
<label for="repository_username" class="col-sm-1 control-label text-left">Username</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.formValues.RepositoryUsername" name="repository_username" placeholder="myGitUser" />
|
||||
</div>
|
||||
<label for="repository_password" class="col-sm-1 control-label text-left">
|
||||
Password
|
||||
</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input type="password" class="form-control" ng-model="$ctrl.formValues.RepositoryPassword" name="repository_password" placeholder="myPassword" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<git-form ng-if="state.Method === 'repository'" model="$ctrl.formValues" on-change="($ctrl.onChangeFormValues)"></git-form>
|
||||
<!-- !repository -->
|
||||
<por-access-control-form form-data="$ctrl.formValues.AccessControlData"></por-access-control-form>
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class CreateCustomTemplateViewController {
|
|||
this.createCustomTemplateFromGitRepository = this.createCustomTemplateFromGitRepository.bind(this);
|
||||
this.editorUpdate = this.editorUpdate.bind(this);
|
||||
this.onChangeMethod = this.onChangeMethod.bind(this);
|
||||
this.onChangeFormValues = this.onChangeFormValues.bind(this);
|
||||
}
|
||||
|
||||
createCustomTemplate() {
|
||||
|
@ -150,6 +151,10 @@ class CreateCustomTemplateViewController {
|
|||
this.state.isEditorDirty = true;
|
||||
}
|
||||
|
||||
onChangeFormValues(newValues) {
|
||||
this.formValues = newValues;
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
const applicationState = this.StateManager.getState();
|
||||
|
||||
|
|
|
@ -53,6 +53,16 @@ angular
|
|||
}
|
||||
};
|
||||
|
||||
$scope.onChangeFormValues = onChangeFormValues;
|
||||
|
||||
$scope.addEnvironmentVariable = function () {
|
||||
$scope.formValues.Env.push({ name: '', value: '' });
|
||||
};
|
||||
|
||||
$scope.removeEnvironmentVariable = function (index) {
|
||||
$scope.formValues.Env.splice(index, 1);
|
||||
};
|
||||
|
||||
function validateForm(accessControlData, isAdmin) {
|
||||
$scope.state.formValidationError = '';
|
||||
var error = '';
|
||||
|
@ -236,4 +246,8 @@ angular
|
|||
};
|
||||
|
||||
initView();
|
||||
|
||||
function onChangeFormValues(newValues) {
|
||||
$scope.formValues = newValues;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -130,79 +130,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- !upload -->
|
||||
<!-- repository -->
|
||||
<div ng-show="state.Method === 'repository'">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Git repository
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can use the URL of a git repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_url" class="col-sm-2 control-label text-left">Repository URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="formValues.RepositoryURL"
|
||||
id="stack_repository_url"
|
||||
placeholder="https://github.com/portainer/portainer-compose"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Specify a reference of the repository using the following syntax: branches with <code>refs/heads/branch_name</code> or tags with <code>refs/tags/tag_name</code>. If
|
||||
not specified, will use the default <code>HEAD</code> reference normally the <code>master</code> branch.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_url" class="col-sm-2 control-label text-left">Repository reference</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="formValues.RepositoryReferenceName" id="stack_repository_reference_name" placeholder="refs/heads/master" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Indicate the path to the Compose file from the root of your repository.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="stack_repository_path" class="col-sm-2 control-label text-left">Compose path</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="formValues.ComposeFilePathInRepository" id="stack_repository_path" placeholder="docker-compose.yml" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">
|
||||
Authentication
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="formValues.RepositoryAuthentication" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="formValues.RepositoryAuthentication">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
If your git account has 2FA enabled, you may receive an <code>authentication required</code> error when deploying your stack. In this case, you will need to provide
|
||||
a personal-access token instead of your password.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group" ng-if="formValues.RepositoryAuthentication">
|
||||
<label for="repository_username" class="col-sm-1 control-label text-left">Username</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input type="text" class="form-control" ng-model="formValues.RepositoryUsername" name="repository_username" placeholder="myGitUser" />
|
||||
</div>
|
||||
<label for="repository_password" class="col-sm-1 control-label text-left">
|
||||
Password
|
||||
</label>
|
||||
<div class="col-sm-11 col-md-5">
|
||||
<input type="password" class="form-control" ng-model="formValues.RepositoryPassword" name="repository_password" placeholder="myPassword" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !repository -->
|
||||
<git-form ng-if="state.Method === 'repository'" model="formValues" on-change="(onChangeFormValues)"></git-form>
|
||||
<!-- custom-template -->
|
||||
<div ng-show="state.Method === 'template'">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
</div>
|
||||
<!-- !associate -->
|
||||
|
||||
<stack-redeploy-git-form ng-if="stack.GitConfig" model="stack.GitConfig" stack="stack" authorization="PortainerStackUpdate"> </stack-redeploy-git-form>
|
||||
<stack-duplication-form
|
||||
ng-if="regular && endpoints.length > 0"
|
||||
endpoints="endpoints"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue