[release] 0.9.11
This commit is contained in:
parent
8e9649ec2c
commit
26d5fe5767
10
changelog.md
10
changelog.md
|
@ -1,3 +1,13 @@
|
|||
## Version 0.9.11
|
||||
- Add support for port ranges in cosmos-compose
|
||||
- Fix bug where multiple host port to the same container would override each other
|
||||
- Port display on Servapp tab was inverted
|
||||
- Fixed Network screen to support complex port mappings
|
||||
- Add support for protocol in cosmos-compose port exposing logic
|
||||
- Add support for relative bind path in docker-compose import
|
||||
- Fix environment vars and labels containing multiple equals (@jwr1)
|
||||
- Fix link to Other Setups page (@jwr1)
|
||||
|
||||
## Version 0.9.10
|
||||
- Never ban gateway ips
|
||||
- Prevent deleting networks if there's an error on disconnect
|
||||
|
|
|
@ -199,7 +199,7 @@ const DockerComposeImport = ({ refresh, dockerComposeInit, installerInit, defaul
|
|||
let volumeObj = {
|
||||
source: volumeSplit[0],
|
||||
target: volumeSplit[1],
|
||||
type: volume[0] === '/' ? 'bind' : 'volume',
|
||||
type: (volume[0] === '/' || volume[0] === '.') ? 'bind' : 'volume',
|
||||
};
|
||||
volumes.push(volumeObj);
|
||||
}
|
||||
|
@ -208,6 +208,14 @@ const DockerComposeImport = ({ refresh, dockerComposeInit, installerInit, defaul
|
|||
}
|
||||
}
|
||||
|
||||
if(doc.services[key].volumes)
|
||||
Object.values(doc.services[key].volumes).forEach((volume) => {
|
||||
if (volume.source && volume.source[0] === '.') {
|
||||
let defaultPath = (config && config.DockerConfig && config.DockerConfig.DefaultDataPath) || "/usr"
|
||||
volume.source = defaultPath + volume.source.replace('.', '');
|
||||
}
|
||||
});
|
||||
|
||||
// convert expose
|
||||
if (doc.services[key].expose) {
|
||||
doc.services[key].expose = doc.services[key].expose.map((port) => {
|
||||
|
|
|
@ -68,25 +68,22 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh, newContainer, O
|
|||
<Formik
|
||||
initialValues={{
|
||||
networkMode: containerInfo.HostConfig.NetworkMode,
|
||||
ports: Object.keys(containerInfo.NetworkSettings.Ports).map((port) => {
|
||||
ports: Object.keys(containerInfo.NetworkSettings.Ports).map((contPort) => {
|
||||
return containerInfo.NetworkSettings.Ports[contPort] ? containerInfo.NetworkSettings.Ports[contPort].map((hostPort) => {
|
||||
return {
|
||||
port: port.split('/')[0],
|
||||
protocol: port.split('/')[1],
|
||||
hostPort: containerInfo.NetworkSettings.Ports[port] && containerInfo.NetworkSettings.Ports[port][0] ?
|
||||
containerInfo.NetworkSettings.Ports[port][0].HostPort : '',
|
||||
port: contPort.split('/')[0],
|
||||
protocol: contPort.split('/')[1],
|
||||
hostPort: hostPort.HostPort,
|
||||
};
|
||||
})
|
||||
}) : {
|
||||
port: contPort.split('/')[0],
|
||||
protocol: contPort.split('/')[1],
|
||||
hostPort: '',
|
||||
}
|
||||
}).flat(),
|
||||
}}
|
||||
validate={(values) => {
|
||||
const errors = {};
|
||||
// check unique
|
||||
const ports = values.ports.map((port) => {
|
||||
return `${port.port}/${port.protocol}`;
|
||||
});
|
||||
const unique = [...new Set(ports)];
|
||||
if (unique.length !== ports.length) {
|
||||
errors.submit = 'Ports must be unique';
|
||||
}
|
||||
OnChange && OnChange(values);
|
||||
return errors;
|
||||
}}
|
||||
|
@ -98,12 +95,14 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh, newContainer, O
|
|||
networkMode: values.networkMode,
|
||||
};
|
||||
values.ports.forEach((port) => {
|
||||
let key = `${port.port}/${port.protocol}`;
|
||||
|
||||
if (port.hostPort) {
|
||||
realvalues.portBindings[`${port.port}/${port.protocol}`] = [
|
||||
{
|
||||
if(!realvalues.portBindings[key]) realvalues.portBindings[key] = [];
|
||||
|
||||
realvalues.portBindings[`${port.port}/${port.protocol}`].push({
|
||||
HostPort: port.hostPort,
|
||||
}
|
||||
];
|
||||
})
|
||||
}
|
||||
});
|
||||
return API.docker.updateContainer(containerInfo.Name.replace('/', ''), realvalues)
|
||||
|
|
|
@ -208,7 +208,7 @@ const ServApps = () => {
|
|||
<Stack style={noOver} margin={1} direction="row" spacing={1}>
|
||||
{app.Ports.filter(p => p.IP != '::').map((port) => {
|
||||
return <Tooltip title={port.PublicPort ? 'Warning, this port is publicly accessible' : ''}>
|
||||
<Chip style={{ fontSize: '80%' }} label={port.PrivatePort + (port.PublicPort ? (":" + port.PublicPort) : '')} color={port.PublicPort ? 'warning' : 'default'} />
|
||||
<Chip style={{ fontSize: '80%' }} label={(port.PublicPort ? (port.PublicPort + ":") : '') + port.PrivatePort} color={port.PublicPort ? 'warning' : 'default'} />
|
||||
</Tooltip>
|
||||
})}
|
||||
</Stack>
|
||||
|
|
|
@ -206,6 +206,24 @@ func CreateServiceRoute(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// generatePorts is a helper function to generate a slice of ports from a string range.
|
||||
func generatePorts(portRangeStr string) []string {
|
||||
portsStr := strings.Split(portRangeStr, "-")
|
||||
if len(portsStr) != 2 {
|
||||
return []string{
|
||||
portsStr[0],
|
||||
}
|
||||
}
|
||||
start, _ := strconv.Atoi(portsStr[0])
|
||||
end, _ := strconv.Atoi(portsStr[1])
|
||||
|
||||
ports := make([]string, end-start+1)
|
||||
for i := range ports {
|
||||
ports[i] = strconv.Itoa(start + i)
|
||||
}
|
||||
|
||||
return ports
|
||||
}
|
||||
|
||||
func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)) error {
|
||||
utils.ConfigLock.Lock()
|
||||
|
@ -408,24 +426,69 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
|||
}
|
||||
|
||||
// For Expose / Ports
|
||||
|
||||
for _, expose := range container.Expose {
|
||||
exposePort := nat.Port(expose)
|
||||
containerConfig.ExposedPorts[exposePort] = struct{}{}
|
||||
}
|
||||
|
||||
PortBindings := nat.PortMap{}
|
||||
finalPorts := []string{}
|
||||
|
||||
for _, port := range container.Ports {
|
||||
portHost := strings.Split(port, ":")[0]
|
||||
portContainer := strings.Split(port, ":")[1]
|
||||
for _, portRaw := range container.Ports {
|
||||
portStuff := strings.Split(portRaw, "/")
|
||||
|
||||
containerConfig.ExposedPorts[nat.Port(portContainer)] = struct{}{}
|
||||
PortBindings[nat.Port(portContainer)] = []nat.PortBinding{
|
||||
{
|
||||
HostIP: "",
|
||||
HostPort: portHost,
|
||||
},
|
||||
if len(portStuff) == 1 {
|
||||
portStuff = append(portStuff, "tcp")
|
||||
}
|
||||
|
||||
port, protocol := portStuff[0], portStuff[1]
|
||||
|
||||
ports := strings.Split(port, ":")
|
||||
|
||||
hostPorts := generatePorts(ports[0])
|
||||
containerPorts := generatePorts(ports[1])
|
||||
|
||||
for i := 0; i < utils.Max(len(hostPorts), len(containerPorts)); i++ {
|
||||
hostPort := hostPorts[i%len(hostPorts)]
|
||||
containerPort := containerPorts[i%len(containerPorts)]
|
||||
|
||||
finalPorts = append(finalPorts, fmt.Sprintf("%s:%s/%s", hostPort, containerPort, protocol))
|
||||
}
|
||||
}
|
||||
|
||||
utils.Debug(fmt.Sprintf("Final ports: %s", finalPorts))
|
||||
|
||||
hostPortsBound := make(map[string]bool)
|
||||
|
||||
for _, portRaw := range finalPorts {
|
||||
portStuff := strings.Split(portRaw, "/")
|
||||
port, protocol := portStuff[0], portStuff[1]
|
||||
nextPort := strings.Split(port, ":")
|
||||
hostPort, contPort := nextPort[0], nextPort[1]
|
||||
|
||||
contPort = contPort + "/" + protocol
|
||||
|
||||
if hostPortsBound[hostPort] {
|
||||
utils.Warn("Port " + hostPort + " already bound, skipping")
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the existing bindings for this container port, if any
|
||||
bindings := PortBindings[nat.Port(contPort)]
|
||||
|
||||
// Append a new PortBinding to the slice of bindings
|
||||
bindings = append(bindings, nat.PortBinding{
|
||||
HostPort: hostPort,
|
||||
})
|
||||
|
||||
// Update the port bindings for this container port
|
||||
PortBindings[nat.Port(contPort)] = bindings
|
||||
|
||||
// Mark the container port as exposed
|
||||
containerConfig.ExposedPorts[nat.Port(contPort)] = struct{}{}
|
||||
|
||||
hostPortsBound[hostPort] = true
|
||||
}
|
||||
|
||||
// Create missing folders for bind mounts
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"fmt"
|
||||
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
containerType "github.com/docker/docker/api/types/container"
|
||||
|
@ -77,6 +78,7 @@ func UpdateContainerRoute(w http.ResponseWriter, req *http.Request) {
|
|||
container.Config.Labels = form.Labels
|
||||
}
|
||||
if(form.PortBindings != nil) {
|
||||
utils.Debug(fmt.Sprintf("UpdateContainer: PortBindings: %v", form.PortBindings))
|
||||
container.HostConfig.PortBindings = form.PortBindings
|
||||
container.Config.ExposedPorts = make(map[nat.Port]struct{})
|
||||
for port := range form.PortBindings {
|
||||
|
|
Loading…
Reference in a new issue