mirror of https://github.com/portainer/portainer
commit
6963a1ae8a
|
@ -76,9 +76,43 @@
|
|||
<tr>
|
||||
<td>Environment:</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li ng-repeat="k in container.Config.Env">{{ k }}</li>
|
||||
</ul>
|
||||
<div ng-show="!editEnv">
|
||||
<button class="btn btn-default btn-xs pull-right" ng-click="editEnv = true"><i class="glyphicon glyphicon-pencil"></i></button>
|
||||
<ul>
|
||||
<li ng-repeat="k in container.Config.Env">{{ k }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-group" ng-show="editEnv">
|
||||
<label>Env:</label>
|
||||
|
||||
<div ng-repeat="envar in newCfg.Env">
|
||||
<div class="form-group form-inline">
|
||||
<div class="form-group">
|
||||
<label class="sr-only">Variable Name:</label>
|
||||
<input type="text" ng-model="envar.name" class="form-control input-sm"
|
||||
placeholder="NAME"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="sr-only">Variable Value:</label>
|
||||
<input type="text" ng-model="envar.value" class="form-control input-sm" style="width: 400px"
|
||||
placeholder="value"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-danger btn-sm input-sm form-control"
|
||||
ng-click="rmEntry(newCfg.Env, envar)"><i class="glyphicon glyphicon-remove"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success btn-sm"
|
||||
ng-click="addEntry(newCfg.Env, {name: '', value: ''})"><i class="glyphicon glyphicon-plus"></i> Add
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm"
|
||||
ng-click="restartEnv()"
|
||||
ng-show="!container.State.Restarting">Commit and restart</button>
|
||||
</div>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -104,11 +138,42 @@
|
|||
<tr>
|
||||
<td>Ports:</td>
|
||||
<td>
|
||||
<ul style="display:inline-table">
|
||||
<li ng-repeat="(containerport, hostports) in container.NetworkSettings.Ports">
|
||||
{{ containerport }} => <span class="label label-default" ng-repeat="(k,v) in hostports">{{ v.HostIp }}:{{ v.HostPort }}</span>
|
||||
<div ng-show="!editPorts">
|
||||
<button class="btn btn-default btn-xs pull-right" ng-click="editPorts = true"><i class="glyphicon glyphicon-pencil"></i></button>
|
||||
<ul>
|
||||
<li ng-repeat="(containerport, hostports) in container.HostConfig.PortBindings">
|
||||
{{ containerport }} =>
|
||||
<span class="label label-default" style="margin-right: 5px;" ng-repeat="(k,v) in hostports">{{ v.HostIp }}:{{ v.HostPort }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ng-show="editPorts">
|
||||
<div ng-repeat="(containerport, hostports) in newCfg.Ports" style="margin-bottom: 5px;">
|
||||
<label>{{ containerport }}</label>
|
||||
<div style="margin-left: 20px;">
|
||||
<div ng-repeat="(k,v) in hostports" class="form-group form-inline">
|
||||
<div class="form-group">
|
||||
<input type="text" ng-model="v.HostIp" class="form-control input-sm" placeholder="IP address, ex. 0.0.0.0" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" ng-model="v.HostPort" class="form-control input-sm"
|
||||
placeholder="Port" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-danger btn-sm input-sm form-control"
|
||||
ng-click="rmEntry(hostports, v)"><i class="glyphicon glyphicon-remove"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success btn-sm"
|
||||
ng-click="addEntry(hostports, {HostIp: '0.0.0.0', HostPort: ''})"><i class="glyphicon glyphicon-plus"></i> Add
|
||||
</button>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm"
|
||||
ng-click="restartEnv()"
|
||||
ng-show="!container.State.Restarting">Commit and restart</button>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -130,6 +195,44 @@
|
|||
<pre>{{ container.Config.Entrypoint.join(' ') }}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bindings:</td>
|
||||
<td>
|
||||
<div ng-show="!editBinds">
|
||||
<button class="btn btn-default btn-xs pull-right" ng-click="editBinds = true"><i class="glyphicon glyphicon-pencil"></i></button>
|
||||
|
||||
<ul>
|
||||
<li ng-repeat="b in container.HostConfig.Binds">{{ b }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ng-show="editBinds">
|
||||
<div ng-repeat="(vol, b) in newCfg.Binds" class="form-group form-inline">
|
||||
<div class="form-group">
|
||||
<input type="text" ng-model="b.HostPath" class="form-control input-sm"
|
||||
placeholder="Host path or volume name" style="width: 250px;" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" ng-model="b.ContPath" ng-readonly="b.DefaultBind" class="form-control input-sm" placeholder="Container path" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><input type="checkbox" ng-model="b.ReadOnly" /> read only</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-danger btn-sm input-sm form-control"
|
||||
ng-click="rmEntry(newCfg.Binds, b)"><i class="glyphicon glyphicon-remove"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success btn-sm"
|
||||
ng-click="addEntry(newCfg.Binds, { ContPath: '', HostPath: '', ReadOnly: false, DefaultBind: false })"><i class="glyphicon glyphicon-plus"></i> Add
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm"
|
||||
ng-click="restartEnv()"
|
||||
ng-show="!container.State.Restarting">Commit and restart</button>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Volumes:</td>
|
||||
<td>{{ container.Volumes }}</td>
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
angular.module('container', [])
|
||||
.controller('ContainerController', ['$scope', '$routeParams', '$location', 'Container', 'ContainerCommit', 'Messages', 'ViewSpinner', '$timeout',
|
||||
function ($scope, $routeParams, $location, Container, ContainerCommit, Messages, ViewSpinner, $timeout) {
|
||||
angular.module('container', [])
|
||||
.controller('ContainerController', ['$scope', '$routeParams', '$location', 'Container', 'ContainerCommit', 'Image', 'Messages', 'ViewSpinner', '$timeout',
|
||||
function ($scope, $routeParams, $location, Container, ContainerCommit, Image, Messages, ViewSpinner, $timeout) {
|
||||
$scope.changes = [];
|
||||
$scope.edit = false;
|
||||
$scope.editEnv = false;
|
||||
$scope.editPorts = false;
|
||||
$scope.editBinds = false;
|
||||
$scope.newCfg = {
|
||||
Env: [],
|
||||
Ports: {}
|
||||
};
|
||||
|
||||
var update = function () {
|
||||
ViewSpinner.spin();
|
||||
|
@ -10,6 +16,49 @@ angular.module('container', [])
|
|||
$scope.container = d;
|
||||
$scope.container.edit = false;
|
||||
$scope.container.newContainerName = d.Name;
|
||||
|
||||
// fill up env
|
||||
if (d.Config.Env) {
|
||||
$scope.newCfg.Env = d.Config.Env.map(function (entry) {
|
||||
return {name: entry.split('=')[0], value: entry.split('=')[1]};
|
||||
});
|
||||
}
|
||||
|
||||
// fill up ports
|
||||
$scope.newCfg.Ports = {};
|
||||
angular.forEach(d.Config.ExposedPorts, function(i, port) {
|
||||
if (d.HostConfig.PortBindings && port in d.HostConfig.PortBindings)
|
||||
$scope.newCfg.Ports[port] = d.HostConfig.PortBindings[port];
|
||||
else
|
||||
$scope.newCfg.Ports[port] = [];
|
||||
});
|
||||
|
||||
// fill up bindings
|
||||
$scope.newCfg.Binds = [];
|
||||
var defaultBinds = {};
|
||||
angular.forEach(d.Config.Volumes, function(value, vol) {
|
||||
defaultBinds[vol] = { ContPath: vol, HostPath: '', ReadOnly: false, DefaultBind: true };
|
||||
});
|
||||
angular.forEach(d.HostConfig.Binds, function(binding, i) {
|
||||
var mountpoint = binding.split(':')[0];
|
||||
var vol = binding.split(':')[1] || '';
|
||||
var ro = binding.split(':').length > 2 && binding.split(':')[2] == 'ro';
|
||||
var defaultBind = false;
|
||||
if (vol == '') {
|
||||
vol = mountpoint;
|
||||
mountpoint = '';
|
||||
}
|
||||
|
||||
if (vol in defaultBinds) {
|
||||
delete defaultBinds[vol];
|
||||
defaultBind = true;
|
||||
}
|
||||
$scope.newCfg.Binds.push({ ContPath: vol, HostPath: mountpoint, ReadOnly: ro, DefaultBind: defaultBind });
|
||||
});
|
||||
angular.forEach(defaultBinds, function(bind) {
|
||||
$scope.newCfg.Binds.push(bind);
|
||||
});
|
||||
|
||||
ViewSpinner.stop();
|
||||
}, function (e) {
|
||||
if (e.status === 404) {
|
||||
|
@ -20,6 +69,7 @@ angular.module('container', [])
|
|||
}
|
||||
ViewSpinner.stop();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.start = function () {
|
||||
|
@ -58,6 +108,108 @@ angular.module('container', [])
|
|||
});
|
||||
};
|
||||
|
||||
$scope.restartEnv = function () {
|
||||
var config = angular.copy($scope.container.Config);
|
||||
|
||||
config.Env = $scope.newCfg.Env.map(function(entry) {
|
||||
return entry.name+"="+entry.value;
|
||||
});
|
||||
|
||||
var portBindings = angular.copy($scope.newCfg.Ports);
|
||||
angular.forEach(portBindings, function(item, key) {
|
||||
if (item.length == 0)
|
||||
delete portBindings[key];
|
||||
});
|
||||
|
||||
|
||||
var binds = [];
|
||||
angular.forEach($scope.newCfg.Binds, function(b) {
|
||||
if (b.ContPath != '') {
|
||||
var bindLine = '';
|
||||
if (b.HostPath != '') {
|
||||
bindLine = b.HostPath + ':';
|
||||
}
|
||||
bindLine += b.ContPath;
|
||||
if (b.ReadOnly) {
|
||||
bindLine += ':ro';
|
||||
}
|
||||
if (b.HostPath != '' || !b.DefaultBind) {
|
||||
binds.push(bindLine);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ViewSpinner.spin();
|
||||
ContainerCommit.commit({id: $routeParams.id, tag: $scope.container.Config.Image, config: config }, function (d) {
|
||||
if ('Id' in d) {
|
||||
var imageId = d.Id;
|
||||
Image.inspect({id: imageId}, function(imageData) {
|
||||
// Append current host config to image with new port bindings
|
||||
imageData.Config.HostConfig = angular.copy($scope.container.HostConfig);
|
||||
imageData.Config.HostConfig.PortBindings = portBindings;
|
||||
imageData.Config.HostConfig.Binds = binds;
|
||||
if (imageData.Config.HostConfig.NetworkMode == 'host') {
|
||||
imageData.Config.Hostname = '';
|
||||
}
|
||||
|
||||
Container.create(imageData.Config, function(containerData) {
|
||||
if (!('Id' in containerData)) {
|
||||
Messages.error("Failure", "Container failed to create.");
|
||||
return;
|
||||
}
|
||||
// Stop current if running
|
||||
if ($scope.container.State.Running) {
|
||||
Container.stop({id: $routeParams.id}, function (d) {
|
||||
Messages.send("Container stopped", $routeParams.id);
|
||||
// start new
|
||||
Container.start({
|
||||
id: containerData.Id
|
||||
}, function (d) {
|
||||
$location.url('/containers/' + containerData.Id + '/');
|
||||
Messages.send("Container started", $routeParams.id);
|
||||
}, function (e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to start." + e.data);
|
||||
});
|
||||
}, function (e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to stop." + e.data);
|
||||
});
|
||||
} else {
|
||||
// start new
|
||||
Container.start({
|
||||
id: containerData.Id
|
||||
}, function (d) {
|
||||
$location.url('/containers/'+containerData.Id+'/');
|
||||
Messages.send("Container started", $routeParams.id);
|
||||
}, function (e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to start." + e.data);
|
||||
});
|
||||
}
|
||||
|
||||
}, function(e) {
|
||||
update();
|
||||
Messages.error("Failure", "Image failed to get." + e.data);
|
||||
});
|
||||
}, function (e) {
|
||||
update();
|
||||
Messages.error("Failure", "Image failed to get." + e.data);
|
||||
})
|
||||
|
||||
} else {
|
||||
update();
|
||||
Messages.error("Failure", "Container commit failed.");
|
||||
}
|
||||
|
||||
|
||||
}, function (e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to commit." + e.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.commit = function () {
|
||||
ViewSpinner.spin();
|
||||
ContainerCommit.commit({id: $routeParams.id, repo: $scope.container.Config.Image}, function (d) {
|
||||
|
@ -139,6 +291,19 @@ angular.module('container', [])
|
|||
$scope.container.edit = false;
|
||||
};
|
||||
|
||||
$scope.addEntry = function (array, entry) {
|
||||
array.push(entry);
|
||||
};
|
||||
$scope.rmEntry = function (array, entry) {
|
||||
var idx = array.indexOf(entry);
|
||||
array.splice(idx, 1);
|
||||
};
|
||||
|
||||
$scope.toggleEdit = function() {
|
||||
$scope.edit = !$scope.edit;
|
||||
};
|
||||
|
||||
update();
|
||||
$scope.getChanges();
|
||||
}]);
|
||||
|
||||
|
|
|
@ -31,8 +31,10 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
url: Settings.url + '/commit',
|
||||
params: {
|
||||
'container': params.id,
|
||||
'repo': params.repo
|
||||
}
|
||||
'tag': params.tag || null,
|
||||
'repo': params.repo || null
|
||||
},
|
||||
data: params.config
|
||||
}).success(callback).error(function (data, status, headers, config) {
|
||||
console.log(error, data);
|
||||
});
|
||||
|
@ -92,7 +94,8 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
insert: {method: 'POST', params: {id: '@id', action: 'insert'}},
|
||||
push: {method: 'POST', params: {id: '@id', action: 'push'}},
|
||||
tag: {method: 'POST', params: {id: '@id', action: 'tag', force: 0, repo: '@repo', tag: '@tag'}},
|
||||
remove: {method: 'DELETE', params: {id: '@id'}, isArray: true}
|
||||
remove: {method: 'DELETE', params: {id: '@id'}, isArray: true},
|
||||
inspect: {method: 'GET', params: {id: '@id', action: 'json'}}
|
||||
});
|
||||
}])
|
||||
.factory('Version', ['$resource', 'Settings', function VersionFactory($resource, Settings) {
|
||||
|
|
Loading…
Reference in New Issue