mirror of https://github.com/docker/docs.git
Updated support for port edit and improved exposed ports shown
Signed-off-by: FrenchBen <me(at)frenchben.com>
This commit is contained in:
parent
429a658884
commit
926908cc99
|
|
@ -2,6 +2,8 @@ import _ from 'underscore';
|
|||
import React from 'react/addons';
|
||||
import shell from 'shell';
|
||||
import ContainerUtil from '../utils/ContainerUtil';
|
||||
import containerActions from '../actions/ContainerActions';
|
||||
import containerStore from '../stores/ContainerStore';
|
||||
import metrics from '../utils/MetricsUtil';
|
||||
import {webPorts} from '../utils/Util';
|
||||
|
||||
|
|
@ -11,50 +13,88 @@ var ContainerSettingsPorts = React.createClass({
|
|||
},
|
||||
getInitialState: function () {
|
||||
return {
|
||||
ports: {},
|
||||
defaultPort: null
|
||||
ports: ContainerUtil.ports(this.props.container)
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if (!this.props.container) {
|
||||
return;
|
||||
}
|
||||
var ports = ContainerUtil.ports(this.props.container);
|
||||
this.setState({
|
||||
ports: ports,
|
||||
defaultPort: _.find(_.keys(ports), function (port) {
|
||||
return webPorts.indexOf(port) !== -1;
|
||||
})
|
||||
});
|
||||
},
|
||||
handleViewLink: function (url) {
|
||||
metrics.track('Opened In Browser', {
|
||||
from: 'settings'
|
||||
});
|
||||
shell.openExternal(url);
|
||||
},
|
||||
handleChangeDefaultPort: function (port, e) {
|
||||
if (e.target.checked) {
|
||||
this.setState({
|
||||
defaultPort: port
|
||||
handleChangePort: function(key, e) {
|
||||
var ports = this.state.ports;
|
||||
var port = e.target.value;
|
||||
|
||||
// save updated port
|
||||
ports[key] = _.extend(ports[key], {
|
||||
url: 'http://' + ports[key]['ip'] + ':' + port,
|
||||
port: port,
|
||||
error: null
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
defaultPort: null
|
||||
|
||||
// basic validation, if number is integer, if its in range, if there
|
||||
// is no collision with ports of other containers and also if there is no
|
||||
// collision with ports for current containser
|
||||
const name = this.props.container.Name;
|
||||
const containers = containerStore.getState().containers;
|
||||
const container = ContainerUtil.isPortCollision(name, containers, port);
|
||||
const duplicates = _.filter(ports, (v, i) => {
|
||||
return (i != key && _.isEqual(v.port, port));
|
||||
});
|
||||
if (!port.match(/^[0-9]+$/g)) {
|
||||
ports[key].error = 'Needs to be an integer.';
|
||||
}
|
||||
else if (port <= 0 || port > 65535) {
|
||||
ports[key].error = 'Needs to be in range <1,65535>.';
|
||||
}
|
||||
else if (container) {
|
||||
ports[key].error = 'Collision with port at container "'+ container.Name +'"';
|
||||
}
|
||||
else if (duplicates.length > 0) {
|
||||
ports[key].error = "Collision with other port at container.";
|
||||
}
|
||||
else if (port == 22 || port == 2376) {
|
||||
ports[key].error = "Ports 22 and 2376 are reserved ports for Kitematic/Docker.";
|
||||
}
|
||||
this.setState({ ports: ports });
|
||||
},
|
||||
handleSave: function() {
|
||||
containerActions.update(this.props.container.Name, {
|
||||
NetworkSettings: {
|
||||
Ports: _.reduce(this.state.ports, function(res, value, key) {
|
||||
res[key + '/tcp'] = [{
|
||||
HostIp: value.ip,
|
||||
HostPort: value.port,
|
||||
}];
|
||||
return res;
|
||||
}, {})
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
if (!this.props.container) {
|
||||
return false;
|
||||
}
|
||||
var isUpdating = (this.props.container.State.Updating);
|
||||
var isValid = true;
|
||||
var ports = _.map(_.pairs(this.state.ports), pair => {
|
||||
var key = pair[0];
|
||||
var val = pair[1];
|
||||
var {ip, port, url, error} = pair[1];
|
||||
isValid = (error) ? false : isValid;
|
||||
let ipLink = (this.props.container.State.Running && !this.props.container.State.Paused && !this.props.container.State.ExitCode && !this.props.container.State.Restarting) ? (<a onClick={this.handleViewLink.bind(this, url)}>{ip}</a>):({ip});
|
||||
return (
|
||||
<tr key={key}>
|
||||
<td>{key}</td>
|
||||
<td><a onClick={this.handleViewLink.bind(this, val.url)}>{val.display}</a></td>
|
||||
<td className="bind">
|
||||
{ipLink}:
|
||||
<input
|
||||
type="text"
|
||||
disabled={isUpdating}
|
||||
onChange={this.handleChangePort.bind(this, key)}
|
||||
defaultValue={port} />
|
||||
</td>
|
||||
<td className="error">{error}</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
|
|
@ -66,13 +106,19 @@ var ContainerSettingsPorts = React.createClass({
|
|||
<thead>
|
||||
<tr>
|
||||
<th>DOCKER PORT</th>
|
||||
<th>ACCESS URL</th>
|
||||
<th>MAC IP:PORT</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ports}
|
||||
</tbody>
|
||||
</table>
|
||||
<a className="btn btn-action"
|
||||
disabled={isUpdating || !isValid}
|
||||
onClick={this.handleSave}>
|
||||
Save
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -28,21 +28,42 @@ var ContainerUtil = {
|
|||
}
|
||||
var res = {};
|
||||
var ip = docker.host;
|
||||
_.each(container.NetworkSettings.Ports, function (value, key) {
|
||||
var ports = (container.NetworkSettings.Ports) ? container.NetworkSettings.Ports : (container.HostConfig.PortBindings) ? container.HostConfig.PortBindings : container.Config.ExposedPorts;
|
||||
_.each(ports, function (value, key) {
|
||||
var dockerPort = key.split('/')[0];
|
||||
var localUrl = null;
|
||||
var localUrlDisplay = null;
|
||||
var port = null;
|
||||
if (value && value.length) {
|
||||
var port = value[0].HostPort;
|
||||
localUrl = 'http://' + ip + ':' + port;
|
||||
localUrlDisplay = ip + ':' + port;
|
||||
}
|
||||
res[dockerPort] = {
|
||||
url: localUrl,
|
||||
display: localUrlDisplay
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
});
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if there is port colision with other containers
|
||||
* @param {String} name name of the current container
|
||||
* @param {Array} containers array of all containers
|
||||
* @param {String} port
|
||||
* @return {Object|null} return nothing or container with colision
|
||||
*/
|
||||
isPortCollision: function (name, containers, port) {
|
||||
var interfaces = {};
|
||||
_.forEach(containers, container => {
|
||||
if (container.Name != name) {
|
||||
_.forEach(this.ports(container), (ip) => {
|
||||
interfaces[ip + ':' + port] = container;
|
||||
});
|
||||
}
|
||||
});
|
||||
return interfaces[docker.host + ':' + port];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,27 @@
|
|||
}
|
||||
.table {
|
||||
&.ports {
|
||||
max-width: 500px;
|
||||
input {
|
||||
width: 50px;
|
||||
border: 0;
|
||||
}
|
||||
tr {
|
||||
td {
|
||||
&:first-child {
|
||||
width: 120px;
|
||||
}
|
||||
&.bind {
|
||||
width: 190px;
|
||||
}
|
||||
&.error {
|
||||
text-align: left;
|
||||
color: red;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.volumes {
|
||||
max-width: 100%;
|
||||
|
|
|
|||
Loading…
Reference in New Issue