1
0
Fork 0
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:
Dmitry Salakhov 2021-06-16 09:11:35 +12:00 committed by GitHub
parent 296ecc5960
commit 0b93714de4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 795 additions and 381 deletions

View file

@ -1023,3 +1023,8 @@ json-tree .branch-preview {
overflow-y: auto;
}
/* !uib-typeahead override */
.my-8 {
margin-top: 2rem;
margin-bottom: 2rem;
}

View file

@ -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'">

View file

@ -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;

View file

@ -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';

View file

@ -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;

View file

@ -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>

View file

@ -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: '<',
},
};

View file

@ -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>

View file

@ -0,0 +1,7 @@
export const gitFormComposePathField = {
templateUrl: './git-form-compose-path-field.html',
bindings: {
value: '<',
onChange: '<',
},
};

View file

@ -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>

View file

@ -0,0 +1,7 @@
export const gitFormRefField = {
templateUrl: './git-form-ref-field.html',
bindings: {
value: '<',
onChange: '<',
},
};

View file

@ -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>

View file

@ -0,0 +1,7 @@
export const gitFormUrlField = {
templateUrl: './git-form-url-field.html',
bindings: {
value: '<',
onChange: '<',
},
};

View file

@ -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,
});
};
}
}

View 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>

View file

@ -0,0 +1,10 @@
import controller from './git-form.controller.js';
export const gitForm = {
templateUrl: './git-form.html',
controller,
bindings: {
model: '<',
onChange: '<',
},
};

View 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;

View file

@ -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);

View file

@ -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;

View file

@ -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>

View file

@ -0,0 +1,5 @@
import angular from 'angular';
import gitFormModule from './forms/git-form';
export default angular.module('portainer.app.components', [gitFormModule]).name;

View file

@ -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) {

View file

@ -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' } },
}
);
},

View file

@ -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;
},
]);

View file

@ -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>

View file

@ -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();

View file

@ -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;
}
});

View file

@ -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">

View file

@ -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"