fix(container-creation): add default/override options (#4119)

* fix(container-creation): add default/override options

* fix(container-creation): allow override with empty string on creation

* fix(container-creation): add tooltip & update placeholder

* fix(container-creation): add warning on duplicate
pull/4173/head
itsconquest 2020-08-07 14:10:40 +12:00 committed by GitHub
parent 1b88ca2285
commit b9c2bf487b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 7 deletions

View File

@ -7,6 +7,7 @@ angular.module('portainer.docker').component('porImageRegistry', {
autoComplete: '<', autoComplete: '<',
labelClass: '@', labelClass: '@',
inputClass: '@', inputClass: '@',
onImageChange: '&',
}, },
require: { require: {
form: '^form', form: '^form',

View File

@ -25,6 +25,7 @@
ng-model="$ctrl.model.Image" ng-model="$ctrl.model.Image"
name="image_name" name="image_name"
placeholder="e.g. myImage:myTag" placeholder="e.g. myImage:myTag"
ng-change="$ctrl.onImageChange()"
required required
/> />
</div> </div>

View File

@ -77,6 +77,8 @@ angular.module('portainer.docker').controller('CreateContainerController', [
CpuLimit: 0, CpuLimit: 0,
MemoryLimit: 0, MemoryLimit: 0,
MemoryReservation: 0, MemoryReservation: 0,
CmdMode: 'default',
EntrypointMode: 'default',
NodeName: null, NodeName: null,
capabilities: [], capabilities: [],
LogDriverName: '', LogDriverName: '',
@ -89,6 +91,7 @@ angular.module('portainer.docker').controller('CreateContainerController', [
$scope.state = { $scope.state = {
formValidationError: '', formValidationError: '',
actionInProgress: false, actionInProgress: false,
mode: '',
}; };
$scope.refreshSlider = function () { $scope.refreshSlider = function () {
@ -97,12 +100,18 @@ angular.module('portainer.docker').controller('CreateContainerController', [
}); });
}; };
$scope.onImageNameChange = function () {
$scope.formValues.CmdMode = 'default';
$scope.formValues.EntrypointMode = 'default';
};
$scope.config = { $scope.config = {
Image: '', Image: '',
Env: [], Env: [],
Cmd: '', Cmd: '',
MacAddress: '', MacAddress: '',
ExposedPorts: {}, ExposedPorts: {},
Entrypoint: '',
HostConfig: { HostConfig: {
RestartPolicy: { RestartPolicy: {
Name: 'no', Name: 'no',
@ -212,6 +221,20 @@ angular.module('portainer.docker').controller('CreateContainerController', [
config.Tty = tty; config.Tty = tty;
} }
function prepareCmd(config) {
if (_.isEmpty(config.Cmd) || $scope.formValues.CmdMode == 'default') {
delete config.Cmd;
} else {
config.Cmd = ContainerHelper.commandStringToArray(config.Cmd);
}
}
function prepareEntrypoint(config) {
if ($scope.formValues.EntrypointMode == 'default' || (_.isEmpty(config.Cmd) && _.isEmpty(config.Entrypoint))) {
config.Entrypoint = null;
}
}
function prepareEnvironmentVariables(config) { function prepareEnvironmentVariables(config) {
var env = []; var env = [];
config.Env.forEach(function (v) { config.Env.forEach(function (v) {
@ -368,7 +391,8 @@ angular.module('portainer.docker').controller('CreateContainerController', [
function prepareConfiguration() { function prepareConfiguration() {
var config = angular.copy($scope.config); var config = angular.copy($scope.config);
config.Cmd = ContainerHelper.commandStringToArray(config.Cmd); prepareCmd(config);
prepareEntrypoint(config);
prepareNetworkConfig(config); prepareNetworkConfig(config);
prepareImageConfig(config); prepareImageConfig(config);
preparePortBindings(config); preparePortBindings(config);
@ -386,8 +410,16 @@ angular.module('portainer.docker').controller('CreateContainerController', [
function loadFromContainerCmd() { function loadFromContainerCmd() {
if ($scope.config.Cmd) { if ($scope.config.Cmd) {
$scope.config.Cmd = ContainerHelper.commandArrayToString($scope.config.Cmd); $scope.config.Cmd = ContainerHelper.commandArrayToString($scope.config.Cmd);
} else { $scope.formValues.CmdMode = 'override';
$scope.config.Cmd = ''; }
}
function loadFromContainerEntrypoint() {
if (_.has($scope.config, 'Entrypoint')) {
if ($scope.config.Entrypoint == null) {
$scope.config.Entrypoint = '';
}
$scope.formValues.EntrypointMode = 'override';
} }
} }
@ -577,8 +609,10 @@ angular.module('portainer.docker').controller('CreateContainerController', [
$scope.formValues.AccessControlData.AccessControlEnabled = false; $scope.formValues.AccessControlData.AccessControlEnabled = false;
} }
$scope.fromContainer = fromContainer; $scope.fromContainer = fromContainer;
$scope.state.mode = 'duplicate';
$scope.config = ContainerHelper.configFromContainer(fromContainer.Model); $scope.config = ContainerHelper.configFromContainer(fromContainer.Model);
loadFromContainerCmd(d); loadFromContainerCmd(d);
loadFromContainerEntrypoint(d);
loadFromContainerLogging(d); loadFromContainerLogging(d);
loadFromContainerPortBindings(d); loadFromContainerPortBindings(d);
loadFromContainerVolumes(d); loadFromContainerVolumes(d);
@ -706,7 +740,6 @@ angular.module('portainer.docker').controller('CreateContainerController', [
function create() { function create() {
var oldContainer = null; var oldContainer = null;
HttpRequestHelper.setPortainerAgentTargetHeader($scope.formValues.NodeName); HttpRequestHelper.setPortainerAgentTargetHeader($scope.formValues.NodeName);
return findCurrentContainer().then(setOldContainer).then(confirmCreateContainer).then(startCreationProcess).catch(notifyOnError).finally(final); return findCurrentContainer().then(setOldContainer).then(confirmCreateContainer).then(startCreationProcess).catch(notifyOnError).finally(final);

View File

@ -3,6 +3,16 @@
<rd-header-content> <a ui-sref="docker.containers">Containers</a> &gt; Add container </rd-header-content> <rd-header-content> <a ui-sref="docker.containers">Containers</a> &gt; Add container </rd-header-content>
</rd-header> </rd-header>
<information-panel title-text="Caution" ng-if="state.mode == 'duplicate'">
<span class="small">
<p class="text-muted">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
The new container may fail to start if the image is changed, and settings from the previous container aren't compatible. Common causes include entrypoint, cmd or
<a href="http://portainer.readthedocs.io/en/stable/agent.html" target="_blank">other settings</a> set by an image.
</p>
</span>
</information-panel>
<div class="row"> <div class="row">
<div class="col-lg-12 col-md-12 col-xs-12"> <div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget> <rd-widget>
@ -35,6 +45,7 @@
auto-complete="true" auto-complete="true"
label-class="col-sm-1" label-class="col-sm-1"
input-class="col-sm-11" input-class="col-sm-11"
on-image-change="onImageNameChange()"
></por-image-registry> ></por-image-registry>
<!-- !image-and-registry --> <!-- !image-and-registry -->
<!-- always-pull --> <!-- always-pull -->
@ -192,15 +203,47 @@
<div class="form-group"> <div class="form-group">
<label for="container_command" class="col-sm-2 col-lg-1 control-label text-left">Command</label> <label for="container_command" class="col-sm-2 col-lg-1 control-label text-left">Command</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control" ng-model="config.Cmd" id="container_command" placeholder="e.g. /usr/bin/nginx -t -c /mynginx.conf" /> <div class="input-group">
<div class="input-group-btn">
<button class="btn btn-primary" ng-model="formValues.CmdMode" uib-btn-radio="'default'" style="margin-left: 0px;"> Default</button>
<button class="btn btn-primary" ng-model="formValues.CmdMode" uib-btn-radio="'override'">Override</button>
</div>
<input
type="text"
class="form-control"
ng-model="config.Cmd"
ng-disabled="formValues.CmdMode === 'default'"
id="container_command"
placeholder="e.g. '-logtostderr' '--housekeeping_interval=5s' or /usr/bin/nginx -t -c /mynginx.conf"
/>
</div>
</div> </div>
</div> </div>
<!-- !command-input --> <!-- !command-input -->
<!-- entrypoint-input --> <!-- entrypoint-input -->
<div class="form-group"> <div class="form-group">
<label for="container_entrypoint" class="col-sm-2 col-lg-1 control-label text-left">Entry Point</label> <label for="container_entrypoint" class="col-sm-2 col-lg-1 control-label text-left">
Entrypoint
<portainer-tooltip
position="bottom"
message="When container entrypoint is entered as part of the Command field, set Entrypoint to Override mode and leave blank, else it will revert to default."
></portainer-tooltip>
</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control" ng-model="config.Entrypoint" id="container_entrypoint" placeholder="e.g. /bin/sh -c" /> <div class="input-group">
<div class="input-group-btn">
<label class="btn btn-primary" ng-model="formValues.EntrypointMode" uib-btn-radio="'default'" style="margin-left: 0px;"> Default</label>
<label class="btn btn-primary" ng-model="formValues.EntrypointMode" uib-btn-radio="'override'">Override</label>
</div>
<input
type="text"
class="form-control"
ng-model="config.Entrypoint"
ng-disabled="formValues.EntrypointMode === 'default'"
id="container_entrypoint"
placeholder="e.g. /bin/sh -c"
/>
</div>
</div> </div>
</div> </div>
<!-- !entrypoint-input --> <!-- !entrypoint-input -->