portainer/app/portainer/views/stacks/edit/stack.html

273 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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