portainer/app/docker/views/services/create/createservice.html

489 lines
27 KiB
HTML
Raw Normal View History

<page-header title="'Create service'" breadcrumbs="[{label:'Services', link:'docker.services'}, 'Add service']"> </page-header>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-body>
<form class="form-horizontal" autocomplete="off">
<!-- name-input -->
<div class="form-group">
<label for="service_name" class="col-sm-2 control-label text-left">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" ng-model="formValues.Name" id="service_name" placeholder="e.g. myService" />
</div>
</div>
<!-- !name-input -->
<div class="col-sm-12 form-section-title"> Image configuration </div>
<!-- image-and-registry -->
<por-image-registry
model="formValues.RegistryModel"
auto-complete="true"
label-class="col-sm-1"
input-class="col-sm-11"
endpoint="endpoint"
is-admin="isAdmin"
check-rate-limits="true"
set-validity="setPullImageValidity"
>
</por-image-registry>
<!-- !image-and-registry -->
<div class="col-sm-12 form-section-title"> Scheduling </div>
<!-- scheduling-mode -->
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left"> Scheduling mode </label>
<div class="btn-group btn-group-sm" style="margin-left: 20px">
<label class="btn btn-light" ng-model="formValues.Mode" uib-btn-radio="'global'">Global</label>
<label class="btn btn-light" ng-model="formValues.Mode" uib-btn-radio="'replicated'">Replicated</label>
</div>
</div>
</div>
<div class="form-group form-inline" ng-if="formValues.Mode === 'replicated'">
<div class="col-sm-12">
<label class="control-label text-left"> Replicas </label>
<input type="number" class="form-control" ng-model="formValues.Replicas" id="replicas" placeholder="e.g. 3" style="margin-left: 20px" />
</div>
</div>
<!-- !scheduling-mode -->
<div class="col-sm-12 form-section-title"> Ports configuration </div>
<!-- port-mapping -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Port mapping</label>
<span class="label label-default interactive vertical-center" style="margin-left: 10px" ng-click="addPortBinding()">
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> map additional port
</span>
</div>
<div class="col-sm-12 form-inline mt-2">
<div ng-repeat="portBinding in formValues.Ports" class="mt-1">
<!-- host-port -->
<div class="input-group col-sm-3 input-group-sm">
<span class="input-group-addon">host</span>
<input type="text" class="form-control" ng-model="portBinding.PublishedPort" placeholder="e.g. 80 or 1.2.3.4:80 (optional)" />
</div>
<!-- !host-port -->
<span style="margin: 0 10px 0 10px">
2018-03-13 05:36:53 +00:00
<i class="fa fa-long-arrow-alt-right" aria-hidden="true"></i>
</span>
<!-- container-port -->
<div class="input-group col-sm-3 input-group-sm">
<span class="input-group-addon">container</span>
<input type="text" class="form-control" ng-model="portBinding.TargetPort" placeholder="e.g. 80" />
</div>
<!-- !container-port -->
<!-- protocol-actions -->
<div class="input-group col-sm-5 input-group-sm">
<div class="btn-group btn-group-sm">
<label class="btn btn-light" ng-model="portBinding.Protocol" uib-btn-radio="'tcp'">TCP</label>
<label class="btn btn-light" ng-model="portBinding.Protocol" uib-btn-radio="'udp'">UDP</label>
</div>
<div class="btn-group btn-group-sm">
<label class="btn btn-light" ng-model="portBinding.PublishMode" uib-btn-radio="'ingress'">Ingress</label>
<label class="btn btn-light" ng-model="portBinding.PublishMode" uib-btn-radio="'host'">Host</label>
</div>
<button class="btn btn-dangerlight" type="button" ng-click="removePortBinding($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
<!-- !protocol-actions -->
</div>
</div>
<!-- !port-mapping-input-list -->
</div>
<!-- !port-mapping -->
feat(webhooks): add support for service update webhooks (#2161) * Initial pass at adding webhook controller and routes * Moving some objects around * Cleaning up comments * Fixing syntax, switching to using the docker sdk over building an http client * Adding delete and list functionality * Updating the handler to use the correct permissions. Updating some comments * Fixing some comments * Code cleanup per pull request comments * Cleanup per PR feedback. Syntax error fix * Initial creation of webhook app code * Moving ClientFactory creation out of handler code and instead using the one created by the main process. Removing webhookInspect method and updating the list function to use json filters * Delete now works on the webhook ID vs service ID * WIP - Service creates a webhook. Display will show an existing webhook URL. * Adding the webhook field to the service view. There is now the ability to add or remove a webhook from a service * Moving all api calls to be webhooks vs webhook * Code cleanup. Moving all api calls to be webhooks vs webhook * More conversion of webhook to webhooks? * Moving UI elements around. Starting function for copying to clipboard * Finalizing function for copying to clipboard. Adding button that calls function and copies webhook to clipboard. * Fixing UI issues. Hiding field entirely when there is no webhook * Moving URL crafting to a helper method. The edit pane for service now creates/deletes webhooks immidiately. * style(service-details): update webhook line * feat(api): strip sha when updating an image via the update webhook * Fixing up some copy. Only displying the port if it is not http or https * Fixing tooltip copy. Setting the forceupdate to be true to require an update to occur * Fixing code climate errors * Adding WebhookType field and setting to ServiceWebhook for new webhooks. Renaming ServiceID to resourceID so future work can add new types of webhooks in other resource areas. * Adding the webhook type to the payload to support more types of webhooks in the future. Setting the type correctly when creating one for a service * feat(webhooks): changes related to webhook management * API code cleanup, removing unneeded functions, and updating validation logic * Incorrectly ignoring the error that the webhook did not exist * Re-adding missing error handling. Changing error response to be a 404 vs 500 when token can't find an object * fix(webhooks): close Docker client after service webhook execution
2018-09-03 10:08:03 +00:00
<!-- create-webhook -->
<div ng-if="endpoint.Type !== 4 && isAdmin">
<div class="col-sm-12 form-section-title"> Webhooks </div>
<div class="form-group">
<div class="col-sm-12">
<por-switch-field
label-class="'col-sm-2'"
checked="$ctrl.formValues.Webhook"
label="'Create a service webhook'"
on-change="(handleWebHookChange)"
tooltip="'Create a webhook (or callback URI) to automate the update of this service. 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 service.'"
></por-switch-field>
</div>
feat(webhooks): add support for service update webhooks (#2161) * Initial pass at adding webhook controller and routes * Moving some objects around * Cleaning up comments * Fixing syntax, switching to using the docker sdk over building an http client * Adding delete and list functionality * Updating the handler to use the correct permissions. Updating some comments * Fixing some comments * Code cleanup per pull request comments * Cleanup per PR feedback. Syntax error fix * Initial creation of webhook app code * Moving ClientFactory creation out of handler code and instead using the one created by the main process. Removing webhookInspect method and updating the list function to use json filters * Delete now works on the webhook ID vs service ID * WIP - Service creates a webhook. Display will show an existing webhook URL. * Adding the webhook field to the service view. There is now the ability to add or remove a webhook from a service * Moving all api calls to be webhooks vs webhook * Code cleanup. Moving all api calls to be webhooks vs webhook * More conversion of webhook to webhooks? * Moving UI elements around. Starting function for copying to clipboard * Finalizing function for copying to clipboard. Adding button that calls function and copies webhook to clipboard. * Fixing UI issues. Hiding field entirely when there is no webhook * Moving URL crafting to a helper method. The edit pane for service now creates/deletes webhooks immidiately. * style(service-details): update webhook line * feat(api): strip sha when updating an image via the update webhook * Fixing up some copy. Only displying the port if it is not http or https * Fixing tooltip copy. Setting the forceupdate to be true to require an update to occur * Fixing code climate errors * Adding WebhookType field and setting to ServiceWebhook for new webhooks. Renaming ServiceID to resourceID so future work can add new types of webhooks in other resource areas. * Adding the webhook type to the payload to support more types of webhooks in the future. Setting the type correctly when creating one for a service * feat(webhooks): changes related to webhook management * API code cleanup, removing unneeded functions, and updating validation logic * Incorrectly ignoring the error that the webhook did not exist * Re-adding missing error handling. Changing error response to be a 404 vs 500 when token can't find an object * fix(webhooks): close Docker client after service webhook execution
2018-09-03 10:08:03 +00:00
</div>
</div>
<!-- !create-webhook -->
<!-- access-control -->
<por-access-control-form form-data="formValues.AccessControlData"></por-access-control-form>
<!-- !access-control -->
<!-- actions -->
<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-primary btn-sm"
ng-disabled="state.actionInProgress || !formValues.RegistryModel.Image || !volumesAreValid()"
ng-click="create()"
button-spinner="state.actionInProgress"
>
<span ng-hide="state.actionInProgress">Create the service</span>
<span ng-show="state.actionInProgress">Creating service...</span>
2017-11-12 19:27:28 +00:00
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px">{{ state.formValidationError }}</span>
</div>
</div>
<!-- !actions -->
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-body>
<ul class="nav nav-pills nav-justified">
<li class="active interactive"><a data-target="#command" data-toggle="tab">Command & Logging</a></li>
<li class="interactive"><a data-target="#volumes" data-toggle="tab">Volumes</a></li>
<li class="interactive"><a data-target="#network" data-toggle="tab">Network</a></li>
feat(UX): introduce new env variables UI (#4175) * feat(app): introduce new env vars ui feat(app): introduce new env vars ui feat(UX): WIP new env variables UI feat(UX): update button and placeholder feat(UX): mention .env file in message feat(UX): allow add/remove value & load correctly feat(UX): restrict filesize to 1MB feat(UX): vertical align error message feat(UX): fill UI from file & when switching modes feat(UX): strip un-needed newline character feat(UX): introduce component to other views feat(UX): fix title alignment feat(UX): only populate editor on mode switch when key exists feat(UX): prevent trimming of whitespace on values feat(UX): change editor to async feat(UX): add message describing use feat(UX): Refactor variable text to editorText refactor(app): rename env vars controller refactor(app): move env var explanation to parent refactor(app): order env var panels refactor(app): move simple env vars mode to component refactor(app): parse env vars refactor(app): move styles to css refactor(app): rename functions refactor(container): parse env vars refactor(env-vars): move utils to helper module refactor(env-vars): use util function for parse dot env file fix(env-vars): ignore comments refactor(services): use env vars utils refactor(env-vars): rename files refactor(env-panel): use utils style(stack): revert EnvContent to Env style(service): revert EnvContent to Env style(container): revert EnvContent to Env refactor(env-vars): support default value refactor(service): use new env var component refactor(env-var): use one way data flow refactor(containers): remove unused function * fix(env-vars): prevent using non .env files * refactor(env-vars): move env vars items to a component * feat(app): fixed env vars form validation in Stack * feat(services): disable env form submit if invalid * fix(app): show key pairs correctly * fix(env-var): use the same validation as with kubernetes * fix(env-vars): parse env var Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com> Co-authored-by: Felix Han <felix.han@portainer.io>
2021-06-14 06:59:07 +00:00
<li class="interactive"><a data-target="#env" data-toggle="tab">Env</a></li>
<li class="interactive"><a data-target="#labels" data-toggle="tab">Labels</a></li>
<li class="interactive"><a data-target="#update-config" data-toggle="tab">Update config & Restart</a></li>
<li class="interactive" ng-if="applicationState.endpoint.apiVersion >= 1.25"><a data-target="#secrets" data-toggle="tab">Secrets</a></li>
<li class="interactive"><a data-target="#configs" data-toggle="tab" ng-if="applicationState.endpoint.apiVersion >= 1.3">Configs</a></li>
<li class="interactive"><a data-target="#resources-placement" data-toggle="tab" ng-click="refreshSlider()">Resources & Placement</a></li>
</ul>
<!-- tab-content -->
<div class="tab-content">
<!-- tab-command -->
<div class="tab-pane active" id="command">
<form class="form-horizontal" style="margin-top: 15px">
<div class="col-sm-12 form-section-title"> Command </div>
<!-- command-input -->
<div class="form-group">
<label for="service_command" class="col-sm-2 col-lg-1 control-label text-left">Command</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.Command" id="service_command" placeholder="e.g. /usr/bin/nginx -t -c /mynginx.conf" />
</div>
</div>
<!-- !command-input -->
<!-- entrypoint-input -->
<div class="form-group">
<label for="service_entrypoint" class="col-sm-2 col-lg-1 control-label text-left">Entrypoint</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.EntryPoint" id="service_entrypoint" placeholder="e.g. /bin/sh -c" />
</div>
</div>
<!-- !entrypoint-input -->
<!-- workdir-user-input -->
<div class="form-group">
<label for="service_workingdir" class="col-sm-2 col-lg-1 control-label text-left">Working Dir</label>
<div class="col-sm-4">
<input type="text" class="form-control" ng-model="formValues.WorkingDir" id="service_workingdir" placeholder="e.g. /myapp" />
</div>
<label for="service_user" class="col-sm-1 control-label text-left">User</label>
<div class="col-sm-4">
<input type="text" class="form-control" ng-model="formValues.User" id="service_user" placeholder="e.g. nginx" />
</div>
</div>
<!-- !workdir-user-input -->
<div class="col-sm-12 form-section-title"> Logging </div>
<!-- logging-driver -->
<div class="form-group">
<label for="log-driver" class="col-sm-2 col-lg-1 control-label text-left">Driver</label>
<div class="col-sm-4">
<select class="form-control" ng-model="formValues.LogDriverName" id="log-driver">
<option selected value="">Default logging driver</option>
<option ng-repeat="driver in availableLoggingDrivers" ng-value="driver">{{ driver }}</option>
<option value="none">none</option>
</select>
</div>
<div class="col-sm-5">
<p class="small text-muted">
Logging driver for service that will override the default docker daemon driver. Select Default logging driver if you don't want to override it. Supported
logging drivers can be found
<a href="https://docs.docker.com/engine/admin/logging/overview/#supported-logging-drivers" target="_blank">in the Docker documentation</a>.
</p>
</div>
</div>
<!-- !logging-driver -->
<!-- logging-opts -->
<div class="form-group">
<div class="col-sm-12 mt-1">
<label class="control-label text-left">
Options
<portainer-tooltip
position="'top'"
message="'Add button is disabled unless a driver other than none or default is selected. Options are specific to the selected driver, refer to the driver documentation.'"
></portainer-tooltip>
</label>
<span
class="label label-default interactive vertical-center"
style="margin-left: 10px"
ng-click="!formValues.LogDriverName || formValues.LogDriverName === 'none' || addLogDriverOpt(formValues.LogDriverName)"
>
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> add logging driver option
</span>
</div>
<!-- logging-opts-input-list -->
<div class="col-sm-12 form-inline mt-2">
<div ng-repeat="opt in formValues.LogDriverOpts" class="mt-1">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">option</span>
<input type="text" class="form-control" ng-model="opt.name" placeholder="e.g. FOO" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="opt.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-dangerlight" type="button" ng-click="removeLogDriverOpt($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
</div>
<!-- logging-opts-input-list -->
</div>
<!-- !logging-opts -->
</form>
</div>
<!-- !tab-command -->
<!-- tab-volume -->
<div class="tab-pane" id="volumes">
<form class="form-horizontal" style="margin-top: 15px">
<!-- volumes -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Volume mapping</label>
<span class="label label-default interactive" style="margin-left: 10px" ng-click="addVolume()">
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> map additional volume
</span>
</div>
<!-- volumes-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px">
<div ng-repeat="volume in formValues.Volumes">
<div class="col-sm-12" style="margin-top: 10px">
<!-- volume-line1 -->
<div class="col-sm-12 form-inline">
<!-- container-path -->
<div class="input-group col-sm-6">
<div class="input-group input-group-sm w-full">
<span class="input-group-addon">container</span>
<input type="text" class="form-control" ng-model="volume.Target" placeholder="e.g. /path/in/container" />
</div>
<div class="small text-warning" ng-show="!volume.Target">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Target is required.
</div>
</div>
<!-- !container-path -->
<!-- volume-type -->
<div class="input-group col-sm-5" style="margin-left: 5px; vertical-align: top">
<div class="btn-group btn-group-sm" ng-if="allowBindMounts">
<label class="btn btn-light" ng-model="volume.Type" uib-btn-radio="'volume'" ng-click="volume.Source = null">Volume</label>
<label class="btn btn-light" ng-model="volume.Type" uib-btn-radio="'bind'" ng-click="volume.Source = null">Bind</label>
</div>
<button class="btn btn-dangerlight" type="button" ng-click="removeVolume($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
<!-- !volume-type -->
</div>
<!-- !volume-line1 -->
<!-- volume-line2 -->
<div class="col-sm-12 form-inline" style="margin-top: 5px">
<div style="height: 30px; display: inline-block; vertical-align: top; display: inline-flex; align-items: center">
<i class="fa fa-long-arrow-alt-right" aria-hidden="true"></i>
</div>
<!-- volume -->
<div class="col-sm-6 input-group" ng-if="volume.Type === 'volume'" style="float: none; padding: 0">
<div class="input-group input-group-sm w-full">
<span class="input-group-addon">volume</span>
<select
class="form-control"
ng-model="volume.Source"
ng-options="vol as ((vol.Id|truncate:30) + ' - ' + (vol.Driver|truncate:30)) for vol in availableVolumes"
>
Squashed commit of the following 2.0.1 release fixes: commit f90d6b55d697a24f191ac715238a37b2c17f02ef Author: Chaim Lev-Ari <chiptus@users.noreply.github.com> Date: Wed Jan 13 00:56:19 2021 +0200 feat(service): clear source volume when change type (#4627) * feat(service): clear source volume when change type * feat(service): init volume source to the correct value commit 1b82b450d76cc68d635c7dba47ae303583df0919 Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com> Date: Thu Jan 7 14:47:32 2021 +1300 * bump the APIVersion to 2.0.1 (#4688) commit b78d8048812ea610ddf9499c56f65896eeda3b64 Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com> Date: Wed Dec 30 23:03:43 2020 +1300 Revert "chore(build): bump Kompose version (#4475)" (#4676) This reverts commit 380f106571330e778e2ef8790cc6f2a617643e97. Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com> commit 51b72c12f933d4252e03ec971ee98c7fe6e5af4c Author: Anthony Lapenna <anthony.lapenna@portainer.io> Date: Wed Dec 23 14:45:32 2020 +1300 fix(docker/stack-details): do not display editor tab for external stack (#4650) commit 58c04bdbe362f41bc78212e366200cc6f2661e29 Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com> Date: Tue Dec 22 13:47:11 2020 +1300 + silently continue when downloading artifacts in windows (#4637) commit a6320d522276d9ec9ca7416b0375d63b30b96ab2 Author: cong meng <mcpacino@gmail.com> Date: Tue Dec 22 13:38:54 2020 +1300 fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618) * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) * fix(frontend) rephrase comments (#4629) Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com> Co-authored-by: Simon Meng <simon.meng@portainer.io> Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
2021-01-20 11:02:22 +00:00
<option selected disabled value="">Select a volume</option>
</select>
</div>
<div class="small text-warning" ng-show="!volume.Source">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Source is required.
</div>
</div>
<!-- !volume -->
<!-- bind -->
<div class="input-group input-group-sm col-sm-6" ng-if="volume.Type === 'bind'">
<div class="input-group input-group-sm w-full">
<span class="input-group-addon">host</span>
<input type="text" class="form-control" ng-model="volume.Source" placeholder="e.g. /path/on/host" />
</div>
<div class="small text-warning" ng-show="!volume.Source">
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Source is required.
</div>
</div>
<!-- !bind -->
<!-- read-only -->
<div class="input-group input-group-sm col-sm-5" style="margin-left: 5px; vertical-align: top">
<div class="btn-group btn-group-sm">
<label class="btn btn-light" ng-model="volume.ReadOnly" uib-btn-radio="false">Writable</label>
<label class="btn btn-light" ng-model="volume.ReadOnly" uib-btn-radio="true">Read-only</label>
</div>
</div>
<!-- !read-only -->
</div>
<!-- !volume-line2 -->
</div>
</div>
</div>
<!-- !volumes-input-list -->
</div>
<!-- !volumes -->
</form>
</div>
<!-- !tab-volume -->
<!-- tab-network -->
<div class="tab-pane" id="network">
<form class="form-horizontal" style="margin-top: 15px">
<!-- network-input -->
<div class="form-group">
<label for="container_network" class="col-sm-2 col-lg-1 control-label text-left">Network</label>
<div class="col-sm-9">
<select class="form-control" ng-model="formValues.Network">
<option selected disabled hidden value="">Select a network</option>
<option ng-repeat="net in availableNetworks | orderBy: 'Name'" ng-value="net.Name">{{ net.Name }}</option>
</select>
</div>
<div class="col-sm-2"></div>
</div>
<!-- !network-input -->
<!-- extra-networks -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Extra networks</label>
<span class="label label-default interactive" style="margin-left: 10px" ng-click="addExtraNetwork()">
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> add extra network
</span>
</div>
<!-- network-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px">
<div ng-repeat="network in formValues.ExtraNetworks" style="margin-top: 2px">
<select class="form-control" ng-model="network.Name">
<option selected disabled hidden value="">Select a network</option>
<option ng-repeat="net in availableNetworks" ng-value="net.Name">{{ net.Name }}</option>
</select>
<button class="btn btn-dangerlight" type="button" ng-click="removeExtraNetwork($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
</div>
<!-- !network-input-list -->
</div>
<!-- !extra-networks -->
<!-- extra-hosts-variables -->
<div class="form-group" ng-if="applicationState.endpoint.apiVersion >= 1.25">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Hosts file entries</label>
<span class="label label-default interactive" style="margin-left: 10px" ng-click="addHostsEntry()">
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> add additional entry
</span>
</div>
<!-- hosts-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px">
<div ng-repeat="variable in formValues.HostsEntries" style="margin-top: 2px">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="variable.value" placeholder="e.g. host:IP" />
</div>
<button class="btn btn-dangerlight" type="button" ng-click="removeHostsEntry($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
</div>
<!-- !hosts-input-list -->
</div>
<!-- !extra-hosts-variables -->
</form>
</div>
<!-- !tab-network -->
feat(UX): introduce new env variables UI (#4175) * feat(app): introduce new env vars ui feat(app): introduce new env vars ui feat(UX): WIP new env variables UI feat(UX): update button and placeholder feat(UX): mention .env file in message feat(UX): allow add/remove value & load correctly feat(UX): restrict filesize to 1MB feat(UX): vertical align error message feat(UX): fill UI from file & when switching modes feat(UX): strip un-needed newline character feat(UX): introduce component to other views feat(UX): fix title alignment feat(UX): only populate editor on mode switch when key exists feat(UX): prevent trimming of whitespace on values feat(UX): change editor to async feat(UX): add message describing use feat(UX): Refactor variable text to editorText refactor(app): rename env vars controller refactor(app): move env var explanation to parent refactor(app): order env var panels refactor(app): move simple env vars mode to component refactor(app): parse env vars refactor(app): move styles to css refactor(app): rename functions refactor(container): parse env vars refactor(env-vars): move utils to helper module refactor(env-vars): use util function for parse dot env file fix(env-vars): ignore comments refactor(services): use env vars utils refactor(env-vars): rename files refactor(env-panel): use utils style(stack): revert EnvContent to Env style(service): revert EnvContent to Env style(container): revert EnvContent to Env refactor(env-vars): support default value refactor(service): use new env var component refactor(env-var): use one way data flow refactor(containers): remove unused function * fix(env-vars): prevent using non .env files * refactor(env-vars): move env vars items to a component * feat(app): fixed env vars form validation in Stack * feat(services): disable env form submit if invalid * fix(app): show key pairs correctly * fix(env-var): use the same validation as with kubernetes * fix(env-vars): parse env var Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com> Co-authored-by: Felix Han <felix.han@portainer.io>
2021-06-14 06:59:07 +00:00
<!-- tab-env -->
<div class="tab-pane" id="env">
<environment-variables-panel
ng-model="formValues.Env"
explanation="These values will be applied to the service when created"
on-change="(handleEnvVarChange)"
></environment-variables-panel>
</div>
<!-- !tab-env -->
<!-- tab-labels -->
<div class="tab-pane" id="labels">
<form class="form-horizontal" style="margin-top: 15px">
<!-- labels -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Service labels</label>
<span class="label label-default interactive" style="margin-left: 10px" ng-click="addLabel()">
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> add service label
</span>
</div>
<!-- labels-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px">
<div ng-repeat="label in formValues.Labels" style="margin-top: 2px">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.key" placeholder="e.g. com.example.foo" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-dangerlight" type="button" ng-click="removeLabel($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
</div>
<!-- !labels-input-list -->
</div>
<!-- !labels-->
<!-- container-labels -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px">
<label class="control-label text-left">Container labels</label>
<span class="label label-default interactive" style="margin-left: 10px" ng-click="addContainerLabel()">
<pr-icon icon="'plus'" mode="'alt'" feather="true"></pr-icon> add container label
</span>
</div>
<!-- container-labels-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px">
<div ng-repeat="label in formValues.ContainerLabels" style="margin-top: 2px">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.key" placeholder="e.g. com.example.foo" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-dangerlight" type="button" ng-click="removeContainerLabel($index)">
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
</div>
<!-- !container-labels-input-list -->
</div>
<!-- !container-labels-->
</form>
</div>
<!-- !tab-labels -->
<!-- tab-update-config -->
<div class="tab-pane" id="update-config" ng-include="'app/docker/views/services/create/includes/update-restart.html'"></div>
<!-- !tab-update-config -->
<!-- tab-secrets -->
<div class="tab-pane" id="secrets" ng-if="applicationState.endpoint.apiVersion >= 1.25" ng-include="'app/docker/views/services/create/includes/secret.html'"></div>
<!-- !tab-secrets -->
<!-- tab-configs -->
<div class="tab-pane" id="configs" ng-if="applicationState.endpoint.apiVersion >= 1.3" ng-include="'app/docker/views/services/create/includes/config.html'"></div>
<!-- !tab-configs -->
<!-- tab-resources-placement -->
<div class="tab-pane" id="resources-placement" ng-include="'app/docker/views/services/create/includes/resources-placement.html'"></div>
<!-- !tab-resources-placement -->
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>