Files
backroad/app/portainer/views/stacks/edit/stack.html
Hao Zhang 37ca62eb06 feat(webhook): teasers of pull images and webhook for EE EE-1332 (#6278)
* feat(webhook): teasers of pull images and webhook for EE
2022-02-14 21:51:43 +08:00

264 lines
13 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 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()"
>
<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>
<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"
>
<i class="fa fa-arrow-right space-right" aria-hidden="true"></i>
<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 reassociate 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"
>
<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 && !stack.FromAppTemplate && !state.actionInProgress"
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="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> <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>
<div ng-if="isAdmin && applicationState.endpoint.type !== 4">
<div class="col-sm-12 form-section-title"> Webhooks </div>
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Create a Stack webhook
<portainer-tooltip
position="top"
message="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."
></portainer-tooltip>
</label>
<label class="switch box-selector-item limited business" style="margin-left: 20px">
<input type="checkbox" ng-model="formValues.EnableWebhook" disabled="disabled" ng-checked="true" /><i></i>
</label>
<be-feature-indicator feature="stackWebhookFeature"></be-feature-indicator>
</div>
</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 dataset="containers" endpoint="endpoint" table-key="stack-containers"></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"
endpoint-public-url="endpoint.PublicURL"
endpoint-id="endpoint.Id"
></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 -->