1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-19 05:19:39 +02:00
portainer/app/portainer/views/stacks/edit/stack.html

245 lines
11 KiB
HTML

<rd-header>
<rd-header-title title-text="Stack details">
<a data-toggle="tooltip" title-text="Refresh" ui-sref="docker.stacks.stack({id: stack.Id})" ui-sref-opts="{reload: true}">
<i class="fa fa-sync" aria-hidden="true"></i>
</a>
</rd-header-title>
<rd-header-content> <a ui-sref="docker.stacks">Stacks</a> &gt; {{ stackName }} </rd-header-content>
</rd-header>
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-body>
<uib-tabset active="state.activeTab">
<!-- tab-info -->
<uib-tab index="0">
<uib-tab-heading> <i class="fa fa-th-list" aria-hidden="true"></i> Stack </uib-tab-heading>
<div style="margin-top: 10px;">
<!-- stack-information -->
<div ng-if="external || orphaned">
<div class="col-sm-12 form-section-title">
Information
</div>
<div class="form-group">
<span class="small">
<p class="text-muted">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
<span ng-if="external">This stack was created outside of Portainer. Control over this stack is limited.</span>
<span ng-if="orphaned">This stack is orphaned. You can reassociate it with the current environment using the "Associate to this endpoint" feature.</span>
</p>
</span>
</div>
</div>
<!-- !stack-information -->
<!-- stack-details -->
<div>
<div class="col-sm-12 form-section-title">
Stack details
</div>
<div class="form-group">
{{ stackName }}
<button
authorization="PortainerStackUpdate"
ng-if="regular && stack.Status === 2"
ng-disabled="state.actionInProgress"
class="btn btn-xs btn-success"
ng-click="startStack()"
>
<i class="fa fa-play space-right" aria-hidden="true"></i>
Start this stack
</button>
<button
ng-if="regular && stack.Status === 1"
authorization="PortainerStackUpdate"
ng-disabled="state.actionInProgress"
class="btn btn-xs btn-danger"
ng-click="stopStack()"
>
<i class="fa fa-stop space-right" aria-hidden="true"></i>
Stop this stack
</button>
<button authorization="PortainerStackDelete" class="btn btn-xs btn-danger" ng-click="removeStack()" ng-if="!external || stack.Type == 1">
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>
Delete this stack
</button>
<button
ng-if="regular && stackFileContent"
class="btn btn-primary btn-xs"
ui-sref="docker.templates.custom.new({fileContent: stackFileContent, type: stack.Type})"
>
<i class="fa fa-plus space-right" aria-hidden="true"></i>
Create template from stack
</button>
</div>
</div>
<!-- !stack-details -->
<!-- associate -->
<div ng-if="orphaned">
<div class="col-sm-12 form-section-title">
Associate to this endpoint
</div>
<p class="small text-muted">
This feature allows you to reassociate this stack to the current endpoint.
</p>
<form class="form-horizontal">
<por-access-control-form form-data="formValues.AccessControlData" hide-title="true"></por-access-control-form>
<div class="form-group">
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
ng-disabled="state.actionInProgress"
ng-click="associateStack()"
button-spinner="state.actionInProgress"
style="margin-left: -5px;"
>
<i class="fa fa-sync" aria-hidden="true" style="margin-right: 3px;"></i>
<span ng-hide="state.actionInProgress">Associate</span>
<span ng-show="state.actionInProgress">Association in progress...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>
</form>
</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"
groups="groups"
current-endpoint-id="currentEndpointId"
on-duplicate="duplicateStack(name, endpointId)"
on-migrate="migrateStack(name, endpointId)"
yaml-error="state.yamlError"
>
</stack-duplication-form>
</div>
</uib-tab>
<!-- !tab-info -->
<!-- tab-file -->
<uib-tab index="1" select="showEditor()" ng-if="!external && !stack.GitConfig">
<uib-tab-heading> <i class="fa fa-pencil-alt space-right" aria-hidden="true"></i> Editor </uib-tab-heading>
<form class="form-horizontal" ng-if="state.showEditorTab" style="margin-top: 10px;" name="stackUpdateForm">
<div class="form-group">
<span class="col-sm-12 text-muted small" style="margin-bottom: 7px;" ng-if="stackType == 2 && composeSyntaxMaxVersion == 2">
This stack will be deployed using the equivalent of <code>docker-compose</code>. Only Compose file format version <b>2</b> is supported at the moment.
</span>
<span class="col-sm-12 text-muted small" style="margin-bottom: 7px;" ng-if="stackType == 2 && composeSyntaxMaxVersion > 2">
This stack will be deployed using <code>docker-compose</code>.
</span>
<span class="col-sm-12 text-muted small">
You can get more information about Compose file format in the <a href="https://docs.docker.com/compose/compose-file/" target="_blank">official documentation</a>.
</span>
</div>
<div class="form-group">
<div class="col-sm-12">
<code-editor
read-only="orphaned"
identifier="stack-editor"
placeholder="# Define or paste the content of your docker-compose file here"
yml="true"
on-change="(editorUpdate)"
value="stackFileContent"
></code-editor>
</div>
</div>
<!-- environment-variables -->
<div ng-if="stack">
<environment-variables-panel
ng-model="formValues.Env"
explanation="These values will be used as substitutions in the stack file"
on-change="(handleEnvVarChange)"
></environment-variables-panel>
</div>
<!-- !environment-variables -->
<!-- options -->
<div ng-if="stack.Type === 1 && applicationState.endpoint.apiVersion >= 1.27" authorization="PortainerStackUpdate">
<div class="col-sm-12 form-section-title">
Options
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="prune" class="control-label text-left">
Prune services
<portainer-tooltip position="bottom" message="Prune services that are no longer referenced."></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px;"> <input name="prune" type="checkbox" ng-model="formValues.Prune" /><i></i> </label>
</div>
</div>
</div>
<!-- !options -->
<div authorization="PortainerStackUpdate">
<div class="col-sm-12 form-section-title">
Actions
</div>
<div class="form-group">
<div class="col-sm-12">
<button
type="button"
class="btn btn-sm btn-primary"
ng-disabled="state.actionInProgress || !stackUpdateForm.$valid || !stackFileContent || orphaned"
ng-click="deployStack()"
button-spinner="state.actionInProgress"
>
<span ng-hide="state.actionInProgress">Update the stack</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>
</div>
</div>
</div>
</form>
</uib-tab>
<!-- !tab-file -->
</uib-tabset>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row" ng-if="containers && (!orphaned || orphanedRunning)">
<div class="col-sm-12">
<containers-datatable
title-text="Containers"
title-icon="fa-cubes"
dataset="containers"
table-key="stack-containers"
order-by="Status"
show-host-column="false"
show-add-action="false"
not-auto-focus="true"
></containers-datatable>
</div>
</div>
<div class="row" ng-if="services && (!orphaned || orphanedRunning)">
<div class="col-sm-12">
<services-datatable
title-text="Services"
title-icon="fa-list-alt"
dataset="services"
table-key="stack-services"
order-by="Name"
nodes="nodes"
agent-proxy="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"
show-ownership-column="false"
show-update-action="applicationState.endpoint.apiVersion >= 1.25"
show-task-logs-button="applicationState.endpoint.apiVersion >= 1.30"
show-add-action="false"
show-stack-column="false"
not-auto-focus="true"
></services-datatable>
</div>
</div>
<!-- access-control-panel -->
<por-access-control-panel ng-if="stack && !orphaned" resource-id="stack.EndpointId + '_' + stack.Name" resource-control="stack.ResourceControl" resource-type="'stack'">
</por-access-control-panel>
<!-- !access-control-panel -->