mirror of https://github.com/portainer/portainer
273 lines
12 KiB
HTML
273 lines
12 KiB
HTML
<page-header title="'Stack details'" breadcrumbs="[{label:'Stacks', link:'docker.stacks'}, stackName]" reload="true"> </page-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>
|
||
<pr-icon icon="'list'"></pr-icon>
|
||
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">
|
||
<pr-icon icon="'alert-triangle'" mode="'warning'" class-name="'mr-0.5'"></pr-icon>
|
||
<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 re-associate it with the current environment using the "Associate to this environment" 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()"
|
||
>
|
||
<pr-icon icon="'play'"></pr-icon>
|
||
Start this stack
|
||
</button>
|
||
|
||
<button
|
||
ng-if="regular && stack.Status === 1"
|
||
authorization="PortainerStackUpdate"
|
||
ng-disabled="state.actionInProgress"
|
||
class="btn btn-xs btn-light"
|
||
ng-click="stopStack()"
|
||
>
|
||
<pr-icon icon="'stop-circle'"></pr-icon>
|
||
Stop this stack
|
||
</button>
|
||
|
||
<button authorization="PortainerStackDelete" class="btn btn-xs btn-light" ng-click="removeStack()" ng-if="!external || stack.Type == 1">
|
||
<pr-icon icon="'trash-2'"></pr-icon>
|
||
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})"
|
||
>
|
||
<pr-icon icon="'plus'"></pr-icon>
|
||
Create template from stack
|
||
</button>
|
||
<button
|
||
authorization="PortainerStackUpdate"
|
||
ng-if="regular && stackFileContent && !stack.FromAppTemplate && stack.GitConfig"
|
||
ng-disabled="state.actionInProgress"
|
||
ng-click="detachStackFromGit()"
|
||
button-spinner="state.actionInProgress"
|
||
class="btn btn-primary btn-xs"
|
||
>
|
||
<pr-icon icon="'arrow-right'" class-name="'mr-1'"></pr-icon>
|
||
<span ng-hide="state.actionInProgress">Detach from Git</span>
|
||
<span ng-show="state.actionInProgress">Detachment in progress...</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<!-- !stack-details -->
|
||
|
||
<!-- associate -->
|
||
<div ng-if="orphaned">
|
||
<div class="col-sm-12 form-section-title"> Associate to this environment </div>
|
||
<p class="small text-muted"> This feature allows you to re-associate this stack to the current environment. </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"
|
||
>
|
||
<pr-icon icon="'refresh-cw'" class="!mr-1"></pr-icon>
|
||
<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 && !stack.FromAppTemplate && !state.actionInProgress"
|
||
model="stack.GitConfig"
|
||
stack="stack"
|
||
authorization="PortainerStackUpdate"
|
||
endpoint="applicationState.endpoint"
|
||
>
|
||
</stack-redeploy-git-form>
|
||
<stack-duplication-form
|
||
ng-if="regular && endpoints.length > 0"
|
||
endpoints="endpoints"
|
||
groups="groups"
|
||
current-endpoint-id="endpoint.Id"
|
||
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 || stack.FromAppTemplate)">
|
||
<uib-tab-heading>
|
||
<pr-icon icon="'edit-2'" class-name="'mr-1'"></pr-icon>
|
||
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 == STACK_TYPES.DockerCompose && 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 == STACK_TYPES.DockerCompose && 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 class="col-sm-12" ng-if="state.yamlError">
|
||
<span class="text-danger small">{{ state.yamlError }}</span>
|
||
</div>
|
||
</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>
|
||
|
||
<div ng-if="isAdmin && applicationState.endpoint.type !== 4">
|
||
<div class="col-sm-12 form-section-title">
|
||
Webhooks
|
||
<por-switch-field
|
||
name="EnableWebhook"
|
||
checked="formValues.EnableWebhook"
|
||
label-class="'col-sm-2'"
|
||
tooltip="'Create a webhook (or callback URI) to automate the update of this stack. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and re-deploy this stack.'"
|
||
label="'Create a Stack webhook'"
|
||
feature-id="'stack-webhook'"
|
||
></por-switch-field>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- environment-variables -->
|
||
<div ng-if="stack">
|
||
<environment-variables-panel
|
||
values="formValues.Env"
|
||
explanation="'These values will be used as substitutions in the stack file. To reference the .env file in your compose file, use ‘stack.env’.'"
|
||
on-change="(handleEnvVarChange)"
|
||
show-help-message="true"
|
||
></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">
|
||
<por-switch-field
|
||
name="prune"
|
||
checked="formValues.Prune"
|
||
tooltip="'Prune services that are no longer referenced.'"
|
||
label-class="'col-sm-2'"
|
||
label="'Prune services'"
|
||
on-change="(onPruneChange)"
|
||
></por-switch-field>
|
||
</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 || state.yamlError || !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>
|
||
|
||
<stack-containers-datatable
|
||
ng-if="stackType !== STACK_TYPES.DockerSwarm && (!orphaned || orphanedRunning)"
|
||
stack-name="stackName"
|
||
environment="endpoint"
|
||
></stack-containers-datatable>
|
||
|
||
<div class="row" ng-if="services && (!orphaned || orphanedRunning)">
|
||
<div class="col-sm-12">
|
||
<services-datatable
|
||
title-text="Services"
|
||
title-icon="list"
|
||
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"
|
||
endpoint-public-url="endpoint.PublicURL"
|
||
endpoint-id="endpoint.Id"
|
||
></services-datatable>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- access-control-panel -->
|
||
<access-control-panel
|
||
ng-if="stack && !orphaned"
|
||
resource-id="stack.EndpointId + '_' + stack.Name"
|
||
resource-control="stack.ResourceControl"
|
||
resource-type="resourceType"
|
||
environment-id="stack.EndpointId"
|
||
on-update-success="(onUpdateResourceControlSuccess)"
|
||
>
|
||
</access-control-panel>
|
||
<!-- !access-control-panel -->
|