mirror of
https://github.com/azukaar/Cosmos-Server.git
synced 2026-05-02 09:09:25 -05:00
[skip ci] pre-0.14
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
- Improved network IP resolution for containers, including supporting any network mode
|
||||
- Integrated MongoDB as container
|
||||
- Removed all sort of container bootstrapping (much faster boot)
|
||||
- Added image clean up
|
||||
- Replaced network clean up by vanilla docker prune
|
||||
|
||||
## Version 0.13.2
|
||||
- Fix display issue with fault network configurations
|
||||
|
||||
@@ -178,9 +178,9 @@ function createService(serviceData, onProgress) {
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/yaml'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: serviceData
|
||||
body: JSON.stringify(serviceData)
|
||||
};
|
||||
|
||||
return fetch('/cosmos/api/docker-service', requestOptions)
|
||||
|
||||
@@ -118,6 +118,7 @@ const ConfigManagement = () => {
|
||||
Email_AllowInsecureTLS : config.EmailConfig.AllowInsecureTLS,
|
||||
|
||||
SkipPruneNetwork: config.DockerConfig.SkipPruneNetwork,
|
||||
SkipPruneImages: config.DockerConfig.SkipPruneImages,
|
||||
DefaultDataPath: config.DockerConfig.DefaultDataPath || "/usr",
|
||||
|
||||
Background: config && config.HomepageConfig && config.HomepageConfig.Background,
|
||||
@@ -175,6 +176,7 @@ const ConfigManagement = () => {
|
||||
DockerConfig: {
|
||||
...config.DockerConfig,
|
||||
SkipPruneNetwork: values.SkipPruneNetwork,
|
||||
SkipPruneImages: values.SkipPruneImages,
|
||||
DefaultDataPath: values.DefaultDataPath
|
||||
},
|
||||
HomepageConfig: {
|
||||
@@ -537,11 +539,17 @@ const ConfigManagement = () => {
|
||||
<MainCard title="Docker">
|
||||
<Stack spacing={2}>
|
||||
<CosmosCheckbox
|
||||
label="Skip Prune Network"
|
||||
label="Do not clean up Network"
|
||||
name="SkipPruneNetwork"
|
||||
formik={formik}
|
||||
/>
|
||||
|
||||
<CosmosCheckbox
|
||||
label="Do not clean up Images"
|
||||
name="SkipPruneImages"
|
||||
formik={formik}
|
||||
/>
|
||||
|
||||
<CosmosInputText
|
||||
label="Default data path for installs"
|
||||
name="DefaultDataPath"
|
||||
|
||||
@@ -35,6 +35,7 @@ import cmp from 'semver-compare';
|
||||
import { HostnameChecker, getHostnameFromName } from '../../../utils/routes';
|
||||
import { CosmosContainerPicker } from '../../config/users/containerPicker';
|
||||
import { randomString } from '../../../utils/indexs';
|
||||
import { has } from 'lodash';
|
||||
|
||||
function checkIsOnline() {
|
||||
API.isOnline().then((res) => {
|
||||
@@ -176,196 +177,244 @@ const DockerComposeImport = ({ refresh, dockerComposeInit, installerInit, defaul
|
||||
try {
|
||||
doc = yaml.load(dockerCompose);
|
||||
|
||||
// if (typeof doc === 'object' && doc !== null && Object.keys(doc).length > 0 &&
|
||||
// !doc.services && !doc.networks && !doc.volumes) {
|
||||
// doc = {
|
||||
// services: Object.assign({}, doc)
|
||||
// }
|
||||
// }
|
||||
if (typeof doc === 'object' && doc !== null && Object.keys(doc).length > 0 &&
|
||||
!doc.services && !doc.networks && !doc.volumes) {
|
||||
doc = {
|
||||
services: Object.assign({}, doc)
|
||||
}
|
||||
}
|
||||
|
||||
// // convert to the proper format
|
||||
// if (doc.services) {
|
||||
// Object.keys(doc.services).forEach((key) => {
|
||||
// // convert volumes
|
||||
// if (doc.services[key].volumes) {
|
||||
// if (Array.isArray(doc.services[key].volumes)) {
|
||||
// let volumes = [];
|
||||
// doc.services[key].volumes.forEach((volume) => {
|
||||
// if (typeof volume === 'object') {
|
||||
// volumes.push(volume);
|
||||
// } else {
|
||||
// let volumeSplit = volume.split(':');
|
||||
// let volumeObj = {
|
||||
// source: volumeSplit[0],
|
||||
// target: volumeSplit[1],
|
||||
// type: (volume[0] === '/' || volume[0] === '.') ? 'bind' : 'volume',
|
||||
// };
|
||||
// volumes.push(volumeObj);
|
||||
// }
|
||||
// });
|
||||
// doc.services[key].volumes = volumes;
|
||||
// }
|
||||
// }
|
||||
// convert to the proper format
|
||||
if (doc.services) {
|
||||
Object.keys(doc.services).forEach((key) => {
|
||||
// convert volumes
|
||||
if (doc.services[key].volumes) {
|
||||
if (Array.isArray(doc.services[key].volumes)) {
|
||||
let volumes = [];
|
||||
doc.services[key].volumes.forEach((volume) => {
|
||||
if (typeof volume === 'object') {
|
||||
volumes.push(volume);
|
||||
} else {
|
||||
let volumeSplit = volume.split(':');
|
||||
let volumeObj = {
|
||||
source: volumeSplit[0],
|
||||
target: volumeSplit[1],
|
||||
type: (volume[0] === '/' || volume[0] === '.') ? 'bind' : 'volume',
|
||||
};
|
||||
volumes.push(volumeObj);
|
||||
}
|
||||
});
|
||||
doc.services[key].volumes = volumes;
|
||||
}
|
||||
}
|
||||
|
||||
// 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('.', '');
|
||||
// }
|
||||
// });
|
||||
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) => {
|
||||
// return '' + port;
|
||||
// })
|
||||
// }
|
||||
// convert expose
|
||||
if (doc.services[key].expose) {
|
||||
doc.services[key].expose = doc.services[key].expose.map((port) => {
|
||||
return '' + port;
|
||||
})
|
||||
}
|
||||
|
||||
// //convert user
|
||||
// if (doc.services[key].user) {
|
||||
// doc.services[key].user = '' + doc.services[key].user;
|
||||
// }
|
||||
//convert user
|
||||
if (doc.services[key].user) {
|
||||
doc.services[key].user = '' + doc.services[key].user;
|
||||
}
|
||||
|
||||
// // convert labels:
|
||||
// if (doc.services[key].labels) {
|
||||
// if (Array.isArray(doc.services[key].labels)) {
|
||||
// let labels = {};
|
||||
// doc.services[key].labels.forEach((label) => {
|
||||
// const [key, value] = label.split(/=(.*)/s);
|
||||
// labels['' + key] = '' + value;
|
||||
// });
|
||||
// doc.services[key].labels = labels;
|
||||
// }
|
||||
// if (typeof doc.services[key].labels == 'object') {
|
||||
// let labels = {};
|
||||
// Object.keys(doc.services[key].labels).forEach((keylabel) => {
|
||||
// labels['' + keylabel] = '' + doc.services[key].labels[keylabel];
|
||||
// });
|
||||
// doc.services[key].labels = labels;
|
||||
// }
|
||||
// }
|
||||
// convert labels:
|
||||
if (doc.services[key].labels) {
|
||||
if (Array.isArray(doc.services[key].labels)) {
|
||||
let labels = {};
|
||||
doc.services[key].labels.forEach((label) => {
|
||||
const [key, value] = label.split(/=(.*)/s);
|
||||
labels['' + key] = '' + value;
|
||||
});
|
||||
doc.services[key].labels = labels;
|
||||
}
|
||||
if (typeof doc.services[key].labels == 'object') {
|
||||
let labels = {};
|
||||
Object.keys(doc.services[key].labels).forEach((keylabel) => {
|
||||
labels['' + keylabel] = '' + doc.services[key].labels[keylabel];
|
||||
});
|
||||
doc.services[key].labels = labels;
|
||||
}
|
||||
}
|
||||
|
||||
// // convert environment
|
||||
// if (doc.services[key].environment) {
|
||||
// if (!Array.isArray(doc.services[key].environment)) {
|
||||
// let environment = [];
|
||||
// Object.keys(doc.services[key].environment).forEach((keyenv) => {
|
||||
// environment.push(keyenv + '=' + doc.services[key].environment[keyenv]);
|
||||
// });
|
||||
// doc.services[key].environment = environment;
|
||||
// }
|
||||
// }
|
||||
// convert environment
|
||||
if (doc.services[key].environment) {
|
||||
if (!Array.isArray(doc.services[key].environment)) {
|
||||
let environment = [];
|
||||
Object.keys(doc.services[key].environment).forEach((keyenv) => {
|
||||
environment.push(keyenv + '=' + doc.services[key].environment[keyenv]);
|
||||
});
|
||||
doc.services[key].environment = environment;
|
||||
}
|
||||
}
|
||||
|
||||
// // convert network
|
||||
// if (doc.services[key].networks) {
|
||||
// if (Array.isArray(doc.services[key].networks)) {
|
||||
// let networks = {};
|
||||
// doc.services[key].networks.forEach((network) => {
|
||||
// if (typeof network === 'object') {
|
||||
// networks['' + network.name] = network;
|
||||
// }
|
||||
// else
|
||||
// networks['' + network] = {};
|
||||
// });
|
||||
// doc.services[key].networks = networks;
|
||||
// }
|
||||
// }
|
||||
// convert network
|
||||
if (doc.services[key].networks) {
|
||||
if (Array.isArray(doc.services[key].networks)) {
|
||||
let networks = {};
|
||||
doc.services[key].networks.forEach((network) => {
|
||||
if (typeof network === 'object') {
|
||||
networks['' + network.name] = network;
|
||||
}
|
||||
else
|
||||
networks['' + network] = {};
|
||||
});
|
||||
doc.services[key].networks = networks;
|
||||
}
|
||||
}
|
||||
|
||||
// // convert devices
|
||||
// if (doc.services[key].devices) {
|
||||
// console.log(1)
|
||||
// if (Array.isArray(doc.services[key].devices)) {
|
||||
// console.log(2)
|
||||
// let devices = [];
|
||||
// doc.services[key].devices.forEach((device) => {
|
||||
// if(device.indexOf(':') === -1) {
|
||||
// devices.push(device + ':' + device);
|
||||
// } else {
|
||||
// devices.push(device);
|
||||
// }
|
||||
// });
|
||||
// doc.services[key].devices = devices;
|
||||
// }
|
||||
// }
|
||||
// convert devices
|
||||
if (doc.services[key].devices) {
|
||||
console.log(1)
|
||||
if (Array.isArray(doc.services[key].devices)) {
|
||||
console.log(2)
|
||||
let devices = [];
|
||||
doc.services[key].devices.forEach((device) => {
|
||||
if(device.indexOf(':') === -1) {
|
||||
devices.push(device + ':' + device);
|
||||
} else {
|
||||
devices.push(device);
|
||||
}
|
||||
});
|
||||
doc.services[key].devices = devices;
|
||||
}
|
||||
}
|
||||
|
||||
// // convert command
|
||||
// if (doc.services[key].command) {
|
||||
// if (typeof doc.services[key].command !== 'string') {
|
||||
// doc.services[key].command = doc.services[key].command.join(' ');
|
||||
// }
|
||||
// }
|
||||
// convert command
|
||||
if (doc.services[key].command) {
|
||||
if (typeof doc.services[key].command !== 'string') {
|
||||
doc.services[key].command = doc.services[key].command.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
// // ensure container_name
|
||||
// if (!doc.services[key].container_name) {
|
||||
// doc.services[key].container_name = key;
|
||||
// }
|
||||
// ensure container_name
|
||||
if (!doc.services[key].container_name) {
|
||||
doc.services[key].container_name = key;
|
||||
}
|
||||
|
||||
// // convert healthcheck
|
||||
// if (doc.services[key].healthcheck) {
|
||||
// const toConvert = ["timeout", "interval", "start_period"];
|
||||
// toConvert.forEach((valT) => {
|
||||
// if(typeof doc.services[key].healthcheck[valT] === 'string') {
|
||||
// let original = doc.services[key].healthcheck[valT];
|
||||
// let value = parseInt(original);
|
||||
// if (original.endsWith('m')) {
|
||||
// value = value * 60;
|
||||
// } else if (original.endsWith('h')) {
|
||||
// value = value * 60 * 60;
|
||||
// } else if (original.endsWith('d')) {
|
||||
// value = value * 60 * 60 * 24;
|
||||
// }
|
||||
// doc.services[key].healthcheck[valT] = value;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// convert healthcheck
|
||||
if (doc.services[key].healthcheck) {
|
||||
const toConvert = ["timeout", "interval", "start_period"];
|
||||
toConvert.forEach((valT) => {
|
||||
if(typeof doc.services[key].healthcheck[valT] === 'string') {
|
||||
let original = doc.services[key].healthcheck[valT];
|
||||
let value = parseInt(original);
|
||||
if (original.endsWith('m')) {
|
||||
value = value * 60;
|
||||
} else if (original.endsWith('h')) {
|
||||
value = value * 60 * 60;
|
||||
} else if (original.endsWith('d')) {
|
||||
value = value * 60 * 60 * 24;
|
||||
}
|
||||
doc.services[key].healthcheck[valT] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// // convert networks
|
||||
// if (doc.networks) {
|
||||
// if (Array.isArray(doc.networks)) {
|
||||
// let networks = {};
|
||||
// doc.networks.forEach((network) => {
|
||||
// if (typeof network === 'object') {
|
||||
// networks['' + network.name] = network;
|
||||
// }
|
||||
// else
|
||||
// networks['' + network] = {};
|
||||
// });
|
||||
// doc.networks = networks;
|
||||
// } else {
|
||||
// let networks = {};
|
||||
// Object.keys(doc.networks).forEach((key) => {
|
||||
// networks['' + key] = doc.networks[key] || {};
|
||||
// });
|
||||
// doc.networks = networks;
|
||||
// }
|
||||
// }
|
||||
// convert networks
|
||||
if (doc.networks) {
|
||||
if (Array.isArray(doc.networks)) {
|
||||
let networks = {};
|
||||
doc.networks.forEach((network) => {
|
||||
if (typeof network === 'object') {
|
||||
networks['' + network.name] = network;
|
||||
}
|
||||
else
|
||||
networks['' + network] = {};
|
||||
});
|
||||
doc.networks = networks;
|
||||
} else {
|
||||
let networks = {};
|
||||
Object.keys(doc.networks).forEach((key) => {
|
||||
networks['' + key] = doc.networks[key] || {};
|
||||
});
|
||||
doc.networks = networks;
|
||||
}
|
||||
}
|
||||
|
||||
// // convert volumes
|
||||
// if (doc.volumes) {
|
||||
// if (Array.isArray(doc.volumes)) {
|
||||
// let volumes = {};
|
||||
// doc.volumes.forEach((volume) => {
|
||||
// if (!volume) {
|
||||
// volume = {};
|
||||
// }
|
||||
// if (typeof volume === 'object') {
|
||||
// volumes['' + volume.name] = volume;
|
||||
// }
|
||||
// else
|
||||
// volumes['' + volume] = {};
|
||||
// });
|
||||
// doc.volumes = volumes;
|
||||
// } else {
|
||||
// let volumes = {};
|
||||
// Object.keys(doc.volumes).forEach((key) => {
|
||||
// volumes['' + key] = doc.volumes[key] || {};
|
||||
// });
|
||||
// doc.volumes = volumes;
|
||||
// }
|
||||
// }
|
||||
// convert volumes
|
||||
if (doc.volumes) {
|
||||
if (Array.isArray(doc.volumes)) {
|
||||
let volumes = {};
|
||||
doc.volumes.forEach((volume) => {
|
||||
if (!volume) {
|
||||
volume = {};
|
||||
}
|
||||
if (typeof volume === 'object') {
|
||||
volumes['' + volume.name] = volume;
|
||||
}
|
||||
else
|
||||
volumes['' + volume] = {};
|
||||
});
|
||||
doc.volumes = volumes;
|
||||
} else {
|
||||
let volumes = {};
|
||||
Object.keys(doc.volumes).forEach((key) => {
|
||||
volumes['' + key] = doc.volumes[key] || {};
|
||||
});
|
||||
doc.volumes = volumes;
|
||||
}
|
||||
}
|
||||
|
||||
// create default network
|
||||
let hasDefaultNetwork = false;
|
||||
if (doc.services) {
|
||||
Object.keys(doc.services).forEach((key) => {
|
||||
if(!doc.services[key].network_mode) {
|
||||
doc.services[key].network_mode = 'cosmos-' + serviceName + '-default';
|
||||
hasDefaultNetwork = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(hasDefaultNetwork) {
|
||||
if(!doc.networks) {
|
||||
doc.networks = {}
|
||||
}
|
||||
|
||||
doc.networks['cosmos-' + serviceName + '-default'] = {
|
||||
Labels: {
|
||||
'cosmos.stack': serviceName,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stack up
|
||||
if (doc.services && Object.keys(doc.services).length > 1) {
|
||||
let hasMain = false;
|
||||
Object.keys(doc.services).forEach((key) => {
|
||||
if(!doc.services[key].labels) {
|
||||
doc.services[key].labels = {};
|
||||
}
|
||||
if(!doc.services[key].labels['cosmos.stack'])
|
||||
doc.services[key].labels['cosmos.stack'] = serviceName;
|
||||
if(doc.services[key].labels['cosmos.stack.main'])
|
||||
hasMain = true;
|
||||
});
|
||||
|
||||
if(!hasMain) {
|
||||
Object.keys(doc.services).forEach((key) => {
|
||||
if(!hasMain) {
|
||||
if(doc.services[key].labels['cosmos.stack'] == serviceName) {
|
||||
doc.services[key].labels['cosmos.stack.main'] = true;
|
||||
hasMain = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
setYmlError(e.message);
|
||||
|
||||
@@ -21,7 +21,6 @@ import { Link } from 'react-router-dom';
|
||||
import { smartDockerLogConcat, tryParseProgressLog } from '../../../utils/docker';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import LogLine from '../../../components/logLine';
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
const preStyle = {
|
||||
backgroundColor: '#000',
|
||||
@@ -85,7 +84,7 @@ const NewDockerService = ({service, refresh}) => {
|
||||
setLog([
|
||||
'Creating Service... ',
|
||||
])
|
||||
API.docker.createService(yaml.dump(service), (newlog) => {
|
||||
API.docker.createService(service, (newlog) => {
|
||||
setLog((old) => smartDockerLogConcat(old, newlog));
|
||||
preRef.current.scrollTop = preRef.current.scrollHeight;
|
||||
if (newlog.includes('[OPERATION SUCCEEDED]')) {
|
||||
@@ -119,7 +118,7 @@ const NewDockerService = ({service, refresh}) => {
|
||||
<pre style={preStyle} ref={preRef}>
|
||||
{!log.length && `
|
||||
# You are about to create the following service(s):
|
||||
${yaml.dump(service)}`
|
||||
${JSON.stringify(service, false ,2)}`
|
||||
}
|
||||
{log.map((l) => {
|
||||
return <LogLine message={tryParseProgressLog(l)} docker isMobile={!screenMin} />
|
||||
|
||||
@@ -85,7 +85,12 @@ const VolumeContainerSetup = ({ noCard, containerInfo, frozenVolumes = [], refre
|
||||
if(newContainer) return;
|
||||
setSubmitting(true);
|
||||
const realvalues = {
|
||||
Volumes: values.volumes
|
||||
Volumes: values.volumes.map((volume) => ({
|
||||
Type: volume.Type,
|
||||
Source: volume.Source,
|
||||
Target: volume.Target,
|
||||
ReadOnly: !volume.RW
|
||||
}))
|
||||
};
|
||||
return API.docker.updateContainer(containerInfo.Name.replace('/', ''), realvalues)
|
||||
.then((res) => {
|
||||
|
||||
@@ -136,9 +136,9 @@ const ServApps = ({stack}) => {
|
||||
|
||||
const servAppsStacked = servApps && servApps.reduce((acc, app) => {
|
||||
// if has label cosmos-stack, add to stack
|
||||
if(!stack && (app.Labels['cosmos-stack'] || app.Labels['com.docker.compose.project'])) {
|
||||
let stackName = app.Labels['cosmos-stack'] || app.Labels['com.docker.compose.project'];
|
||||
let stackMain = app.Labels['cosmos-stack-main'] || (app.Labels['com.docker.compose.container-number'] == '1' && app.Names[0].replace('/', ''));
|
||||
if(!stack && (app.Labels['cosmos-stack'] || app.Labels['cosmos.stack'] || app.Labels['com.docker.compose.project'])) {
|
||||
let stackName = app.Labels['cosmos-stack'] || app.Labels['cosmos.stack'] || app.Labels['com.docker.compose.project'];
|
||||
let stackMain = app.Labels['cosmos-stack-main'] || app.Labels['cosmos.stack.main'] || (app.Labels['com.docker.compose.container-number'] == '1' && app.Names[0].replace('/', ''));
|
||||
|
||||
if(!acc[stackName]) {
|
||||
acc[stackName] = {
|
||||
@@ -190,7 +190,7 @@ const ServApps = ({stack}) => {
|
||||
if(stackMain == app.Names[0].replace('/', '') || !acc[stackName].app) {
|
||||
acc[stackName].app = app;
|
||||
}
|
||||
} else if (!stack || (stack && (app.Labels['cosmos-stack'] === stack || app.Labels['com.docker.compose.project'] === stack))){
|
||||
} else if (!stack || (stack && (app.Labels['cosmos-stack'] === stack || app.Labels['cosmos.stack'] === stack || app.Labels['com.docker.compose.project'] === stack))){
|
||||
// else add to default stack
|
||||
acc[app.Names[0]] = {
|
||||
type: 'app',
|
||||
@@ -370,55 +370,6 @@ const ServApps = ({stack}) => {
|
||||
})}
|
||||
</Stack>
|
||||
</Stack>
|
||||
{app.isUpdating ? <div>
|
||||
<CircularProgress color="inherit" />
|
||||
</div>
|
||||
:
|
||||
<Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
|
||||
<Typography variant="h6" color="text.secondary">
|
||||
Settings {app.type == "app" && (app.state !== 'running' ? '(Start container to edit)' : '')}
|
||||
</Typography>
|
||||
<Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
|
||||
<Checkbox
|
||||
checked={app.labels['cosmos-force-network-secured'] === 'true'}
|
||||
disabled={app.type == "stack" || app.state !== 'running'}
|
||||
onChange={(e) => {
|
||||
const name = app.name.replace('/', '');
|
||||
setIsUpdatingId(name, true);
|
||||
API.docker.secure(name, e.target.checked).then(() => {
|
||||
setTimeout(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
}, 3000);
|
||||
}).catch(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
})
|
||||
}}
|
||||
/> Isolate Container Network <ContainerNetworkWarning container={app.app} />
|
||||
</Stack>
|
||||
<Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
|
||||
<Checkbox
|
||||
checked={app.labels['cosmos-auto-update'] === 'true' ||
|
||||
(selfName && app.name.replace('/', '') == selfName && config.AutoUpdate)}
|
||||
disabled={app.type == "stack" || app.state !== 'running'}
|
||||
onChange={(e) => {
|
||||
const name = app.name.replace('/', '');
|
||||
setIsUpdatingId(name, true);
|
||||
API.docker.autoUpdate(name, e.target.checked).then(() => {
|
||||
setTimeout(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
}, 3000);
|
||||
}).catch(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
})
|
||||
}}
|
||||
/> Auto Update Container
|
||||
</Stack>
|
||||
</Stack>
|
||||
}
|
||||
<Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
|
||||
<Typography variant="h6" color="text.secondary">
|
||||
URLs
|
||||
@@ -443,6 +394,55 @@ const ServApps = ({stack}) => {
|
||||
{/* } */}
|
||||
</Stack>
|
||||
</Stack>
|
||||
{app.isUpdating ? <div>
|
||||
<CircularProgress color="inherit" />
|
||||
</div>
|
||||
:
|
||||
<Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
|
||||
{/* <Typography variant="h6" color="text.secondary">
|
||||
Settings {app.type == "app" && (app.state !== 'running' ? '(Start container to edit)' : '')}
|
||||
</Typography>
|
||||
<Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
|
||||
<Checkbox
|
||||
checked={app.labels['cosmos-force-network-secured'] === 'true'}
|
||||
disabled={app.type == "stack" || app.state !== 'running'}
|
||||
onChange={(e) => {
|
||||
const name = app.name.replace('/', '');
|
||||
setIsUpdatingId(name, true);
|
||||
API.docker.secure(name, e.target.checked).then(() => {
|
||||
setTimeout(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
}, 3000);
|
||||
}).catch(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
})
|
||||
}}
|
||||
/> Isolate Container Network <ContainerNetworkWarning container={app.app} />
|
||||
</Stack> */}
|
||||
<Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
|
||||
<Checkbox
|
||||
checked={app.labels['cosmos-auto-update'] === 'true' ||
|
||||
(selfName && app.name.replace('/', '') == selfName && config.AutoUpdate)}
|
||||
disabled={app.type == "stack" || app.state !== 'running'}
|
||||
onChange={(e) => {
|
||||
const name = app.name.replace('/', '');
|
||||
setIsUpdatingId(name, true);
|
||||
API.docker.autoUpdate(name, e.target.checked).then(() => {
|
||||
setTimeout(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
}, 3000);
|
||||
}).catch(() => {
|
||||
setIsUpdatingId(name, false);
|
||||
refreshServApps();
|
||||
})
|
||||
}}
|
||||
/> Auto Update Container
|
||||
</Stack>
|
||||
</Stack>
|
||||
}
|
||||
<div>
|
||||
<MiniPlotComponent agglo metrics={[
|
||||
"cosmos.system.docker.cpu." + app.name.replace('/', ''),
|
||||
@@ -452,6 +452,7 @@ const ServApps = ({stack}) => {
|
||||
["cosmos.system.docker.ram." + app.name.replace('/', '')]: "RAM"
|
||||
}}/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Link to={app.type === 'stack' ?
|
||||
`/cosmos-ui/servapps/stack/${app.name}` :
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cosmos-server",
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0-unstable1",
|
||||
"description": "",
|
||||
"main": "test-server.js",
|
||||
"bugs": {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<a href="https://github.com/BlackrazorNZ"><img src="https://avatars.githubusercontent.com/BlackrazorNZ" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
|
||||
<a href="https://github.com/DGAzr"><img src="https://avatars.githubusercontent.com/DGAzr" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
|
||||
<a href="https://github.com/eldergod1800"><img src="https://avatars.githubusercontent.com/eldergod1800" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
|
||||
<a href="https://github.com/MELVARDEV"><img src="https://avatars.githubusercontent.com/MELVARDEV" style="border-radius:48px" width="48" height="48" alt="MELVAR" title="MELVAR" /></a>
|
||||
<a href="https://github.com/Quinnus"><img src="https://avatars.githubusercontent.com/Quinnus" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
|
||||
</p><!-- /sponsors -->
|
||||
|
||||
|
||||
+49
-121
@@ -1,7 +1,7 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
// "encoding/json"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os/user"
|
||||
"errors"
|
||||
// "gopkg.in/yaml.v2"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
@@ -230,76 +229,23 @@ func CreateServiceRoute(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// decoder := yaml.NewDecoder(req.Body)
|
||||
// var serviceRequest DockerServiceCreateRequest
|
||||
// err := decoder.Decode(&serviceRequest)
|
||||
// if err != nil {
|
||||
// utils.Error("CreateService - decode - ", err)
|
||||
// fmt.Fprintf(w, "[OPERATION FAILED] Bad request: "+err.Error(), http.StatusBadRequest, "DS003")
|
||||
// flusher.Flush()
|
||||
// utils.HTTPError(w, "Bad request: " + err.Error(), http.StatusBadRequest, "DS003")
|
||||
// return
|
||||
// }
|
||||
decoder := json.NewDecoder(req.Body)
|
||||
var serviceRequest DockerServiceCreateRequest
|
||||
err := decoder.Decode(&serviceRequest)
|
||||
if err != nil {
|
||||
utils.Error("CreateService - decode - ", err)
|
||||
fmt.Fprintf(w, "[OPERATION FAILED] Bad request: "+err.Error(), http.StatusBadRequest, "DS003")
|
||||
flusher.Flush()
|
||||
utils.HTTPError(w, "Bad request: " + err.Error(), http.StatusBadRequest, "DS003")
|
||||
return
|
||||
}
|
||||
|
||||
/*CreateService(serviceRequest,
|
||||
CreateService(serviceRequest,
|
||||
func (msg string) {
|
||||
fmt.Fprintf(w, msg)
|
||||
flusher.Flush()
|
||||
},
|
||||
)*/
|
||||
|
||||
ServiceName := "test-wesh"
|
||||
|
||||
filePath := utils.CONFIGFOLDER + "compose/" + ServiceName
|
||||
|
||||
// Create the folder if does not exist, and output docker-compose.yml
|
||||
if _, err := os.Stat(utils.CONFIGFOLDER + "compose/"); os.IsNotExist(err) {
|
||||
os.MkdirAll(utils.CONFIGFOLDER + "compose/", 0750)
|
||||
}
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
os.MkdirAll(filePath, 0750)
|
||||
}
|
||||
|
||||
// create or truncate the file
|
||||
file, err := os.Create(filePath + "/docker-compose.yml")
|
||||
if err != nil {
|
||||
utils.Error("CreateService - create - ", err)
|
||||
fmt.Fprintf(w, "[OPERATION FAILED] Internal server error: "+err.Error(), http.StatusInternalServerError, "DS004")
|
||||
flusher.Flush()
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// write to file
|
||||
ymlBody := req.Body
|
||||
writer := bufio.NewWriter(file)
|
||||
_, err = writer.ReadFrom(ymlBody)
|
||||
if err != nil {
|
||||
utils.Error("CreateService - write - ", err)
|
||||
fmt.Fprintf(w, "[OPERATION FAILED] Internal server error: "+err.Error(), http.StatusInternalServerError, "DS005")
|
||||
flusher.Flush()
|
||||
return
|
||||
}
|
||||
|
||||
writer.Flush()
|
||||
|
||||
// Compose up
|
||||
err = ComposeUp(filePath, func(message string, outputType int) {
|
||||
fmt.Fprintf(w, "%s\n", message)
|
||||
flusher.Flush()
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
utils.Error("CreateService - composeup - ", err)
|
||||
fmt.Fprintf(w, "[OPERATION FAILED] Internal server error: "+err.Error(), http.StatusInternalServerError, "DS006")
|
||||
flusher.Flush()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Write a response to the client
|
||||
fmt.Fprintf(w, "[OPERATION SUCCESSFUL] Service created successfully", http.StatusOK, "DS007")
|
||||
flusher.Flush()
|
||||
)
|
||||
} else {
|
||||
utils.Error("CreateService: Method not allowed" + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
@@ -340,21 +286,6 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
||||
var rollbackActions []DockerServiceCreateRollback
|
||||
var err error
|
||||
|
||||
serviceName := ""
|
||||
for serviceName = range serviceRequest.Services {
|
||||
break
|
||||
}
|
||||
|
||||
// check if serviceRequest.Networks contains service-default, if not, create it
|
||||
if _, ok := serviceRequest.Networks[serviceName + "-default"]; !ok {
|
||||
serviceRequest.Networks[serviceName + "-default"] = ContainerCreateRequestNetwork{
|
||||
Name: serviceName + "-default",
|
||||
Driver: "bridge",
|
||||
Attachable: true,
|
||||
Internal: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Create networks
|
||||
for networkToCreateName, networkToCreate := range serviceRequest.Networks {
|
||||
utils.Log(fmt.Sprintf("Creating network %s...", networkToCreateName))
|
||||
@@ -365,7 +296,7 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
||||
|
||||
if err == nil {
|
||||
if networkToCreate.Driver == "" {
|
||||
networkToCreate.Driver = serviceName + "-default"
|
||||
networkToCreate.Driver = "bridge"
|
||||
}
|
||||
|
||||
if (exNetworkDef.Driver != networkToCreate.Driver) {
|
||||
@@ -491,51 +422,50 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
||||
OnLog(fmt.Sprintf("Checking service %s...\n", serviceName))
|
||||
|
||||
// If container request a Cosmos network, create and attach it
|
||||
|
||||
/*if (container.Labels["cosmos-force-network-secured"] == "true" || strings.ToLower(container.Labels["cosmos-network-name"]) == "auto") &&
|
||||
container.Labels["cosmos-network-name"] == "" {
|
||||
utils.Log(fmt.Sprintf("Forcing secure %s...", serviceName))
|
||||
OnLog(fmt.Sprintf("Forcing secure %s...\n", serviceName))
|
||||
// if (container.Labels["cosmos-force-network-secured"] == "true" || strings.ToLower(container.Labels["cosmos-network-name"]) == "auto") &&
|
||||
// container.Labels["cosmos-network-name"] == "" {
|
||||
// utils.Log(fmt.Sprintf("Forcing secure %s...", serviceName))
|
||||
// OnLog(fmt.Sprintf("Forcing secure %s...\n", serviceName))
|
||||
|
||||
newNetwork, errNC := CreateCosmosNetwork(serviceName)
|
||||
if errNC != nil {
|
||||
utils.Error("CreateService: Network", err)
|
||||
OnLog(utils.DoErr("Network %s cant be created\n", newNetwork))
|
||||
Rollback(rollbackActions, OnLog)
|
||||
return err
|
||||
}
|
||||
// newNetwork, errNC := CreateCosmosNetwork(serviceName)
|
||||
// if errNC != nil {
|
||||
// utils.Error("CreateService: Network", err)
|
||||
// OnLog(utils.DoErr("Network %s cant be created\n", newNetwork))
|
||||
// Rollback(rollbackActions, OnLog)
|
||||
// return err
|
||||
// }
|
||||
|
||||
container.Labels["cosmos-network-name"] = newNetwork
|
||||
// container.Labels["cosmos-network-name"] = newNetwork
|
||||
|
||||
AttachNetworkToCosmos(newNetwork)
|
||||
// AttachNetworkToCosmos(newNetwork)
|
||||
|
||||
if container.Networks == nil {
|
||||
container.Networks = make(map[string]ContainerCreateRequestServiceNetwork)
|
||||
}
|
||||
// if container.Networks == nil {
|
||||
// container.Networks = make(map[string]ContainerCreateRequestServiceNetwork)
|
||||
// }
|
||||
|
||||
container.Networks[newNetwork] = ContainerCreateRequestServiceNetwork{}
|
||||
// container.Networks[newNetwork] = ContainerCreateRequestServiceNetwork{}
|
||||
|
||||
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
|
||||
Action: "remove",
|
||||
Type: "network",
|
||||
Name: newNetwork,
|
||||
})
|
||||
// rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
|
||||
// Action: "remove",
|
||||
// Type: "network",
|
||||
// Name: newNetwork,
|
||||
// })
|
||||
|
||||
utils.Log(fmt.Sprintf("Created secure network %s", newNetwork))
|
||||
OnLog(fmt.Sprintf("Created secure network %s\n", newNetwork))
|
||||
} else if container.Labels["cosmos-network-name"] != "" {
|
||||
// Container has a declared a Cosmos network, check if it exists and connect to it
|
||||
utils.Log(fmt.Sprintf("Checking declared network %s...", container.Labels["cosmos-network-name"]))
|
||||
OnLog(fmt.Sprintf("Checking declared network %s...\n", container.Labels["cosmos-network-name"]))
|
||||
// utils.Log(fmt.Sprintf("Created secure network %s", newNetwork))
|
||||
// OnLog(fmt.Sprintf("Created secure network %s\n", newNetwork))
|
||||
// } else if container.Labels["cosmos-network-name"] != "" {
|
||||
// // Container has a declared a Cosmos network, check if it exists and connect to it
|
||||
// utils.Log(fmt.Sprintf("Checking declared network %s...", container.Labels["cosmos-network-name"]))
|
||||
// OnLog(fmt.Sprintf("Checking declared network %s...\n", container.Labels["cosmos-network-name"]))
|
||||
|
||||
_, err := DockerClient.NetworkInspect(DockerContext, container.Labels["cosmos-network-name"], doctype.NetworkInspectOptions{})
|
||||
if err == nil {
|
||||
utils.Log(fmt.Sprintf("Connecting to declared network %s...", container.Labels["cosmos-network-name"]))
|
||||
OnLog(fmt.Sprintf("Connecting to declared network %s...\n", container.Labels["cosmos-network-name"]))
|
||||
// _, err := DockerClient.NetworkInspect(DockerContext, container.Labels["cosmos-network-name"], doctype.NetworkInspectOptions{})
|
||||
// if err == nil {
|
||||
// utils.Log(fmt.Sprintf("Connecting to declared network %s...", container.Labels["cosmos-network-name"]))
|
||||
// OnLog(fmt.Sprintf("Connecting to declared network %s...\n", container.Labels["cosmos-network-name"]))
|
||||
|
||||
AttachNetworkToCosmos(container.Labels["cosmos-network-name"])
|
||||
}
|
||||
}*/
|
||||
// AttachNetworkToCosmos(container.Labels["cosmos-network-name"])
|
||||
// }
|
||||
// }
|
||||
|
||||
utils.Log(fmt.Sprintf("Creating container %s...", container.Name))
|
||||
OnLog(fmt.Sprintf("Creating container %s...\n", container.Name))
|
||||
@@ -889,8 +819,6 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
||||
// connect to networks
|
||||
for netName, netConfig := range container.Networks {
|
||||
utils.Log("CreateService: Connecting to network: " + netName)
|
||||
|
||||
//TODO: THIS IS WRONG https://pkg.go.dev/github.com/docker/docker@v24.0.7+incompatible/api/types/network#EndpointSettings
|
||||
err = DockerClient.NetworkConnect(DockerContext, netName, container.Name, &network.EndpointSettings{
|
||||
Aliases: netConfig.Aliases,
|
||||
IPAddress: netConfig.IPV4Address,
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os/exec"
|
||||
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
Stdout = iota
|
||||
Stderr
|
||||
)
|
||||
|
||||
|
||||
// readOutput reads from the given reader and uses the callback function to handle the output.
|
||||
func readOutput(r io.Reader, callback func(message string, outputType int), outputType int) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
callback(scanner.Text(), outputType)
|
||||
}
|
||||
}
|
||||
|
||||
// ExecCommand runs the specified command and uses a callback function to handle the output.
|
||||
func ExecCommand(callback func(message string, outputType int), args ...string) error {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
utils.Debug("Running command: " + cmd.String())
|
||||
|
||||
callback("Running command: " + cmd.String(), Stdout)
|
||||
|
||||
// Create pipes for stdout and stderr
|
||||
stdoutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stderrPipe, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start the command
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read from stdout and stderr in separate goroutines
|
||||
go readOutput(stdoutPipe, callback, Stdout)
|
||||
go readOutput(stderrPipe, callback, Stderr)
|
||||
|
||||
// Wait for the command to finish
|
||||
return cmd.Wait()
|
||||
}
|
||||
|
||||
func ComposeUp(filePath string, callback func(message string, outputType int)) error {
|
||||
return ExecCommand(callback, "docker", "compose", "--project-directory", filePath, "up", "--remove-orphans", "-d")
|
||||
}
|
||||
+15
-84
@@ -9,7 +9,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types"
|
||||
network "github.com/docker/docker/api/types/network"
|
||||
natting "github.com/docker/go-connections/nat"
|
||||
@@ -393,95 +393,26 @@ var DebouncedNetworkCleanUp = _debounceNetworkCleanUp()
|
||||
func NetworkCleanUp() {
|
||||
config := utils.GetMainConfig()
|
||||
|
||||
if(config.DockerConfig.SkipPruneNetwork) {
|
||||
return
|
||||
}
|
||||
|
||||
DockerNetworkLock <- true
|
||||
defer func() { <-DockerNetworkLock }()
|
||||
|
||||
defer func() { <-DockerNetworkLock }()
|
||||
|
||||
utils.Log("Cleaning up orphan networks...")
|
||||
pruneFilters := filters.NewArgs()
|
||||
|
||||
// list every network
|
||||
networks, err := DockerClient.NetworkList(DockerContext, types.NetworkListOptions{})
|
||||
if err != nil {
|
||||
utils.Error("NetworkCleanUpList", err)
|
||||
return
|
||||
if(!config.DockerConfig.SkipPruneNetwork) {
|
||||
report, err := DockerClient.NetworksPrune(DockerContext, pruneFilters)
|
||||
if err != nil {
|
||||
utils.Error("[DOCKER] Error pruning networks", err)
|
||||
}
|
||||
|
||||
utils.Log("Pruned networks: " + fmt.Sprintf("%v", report.NetworksDeleted))
|
||||
}
|
||||
|
||||
|
||||
// check if network is empty or has only self as container
|
||||
for _, networkHollow := range networks {
|
||||
utils.Debug("Checking network: " + networkHollow.Name)
|
||||
|
||||
if(networkHollow.Name == "bridge" || networkHollow.Name == "host" || networkHollow.Name == "none") {
|
||||
continue
|
||||
}
|
||||
|
||||
// inspect network because the Docker API is a complete mess :)
|
||||
network, err := DockerClient.NetworkInspect(DockerContext, networkHollow.ID, types.NetworkInspectOptions{})
|
||||
|
||||
if(!config.DockerConfig.SkipPruneImages) {
|
||||
report, err := DockerClient.ImagesPrune(DockerContext, pruneFilters)
|
||||
if err != nil {
|
||||
utils.Error("NetworkCleanUpInspect", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if(len(network.Containers) > 1) {
|
||||
continue
|
||||
}
|
||||
|
||||
utils.Debug("Ready to Check network: " + network.Name)
|
||||
|
||||
if(len(network.Containers) == 0) {
|
||||
utils.Log("Removing orphan network: " + network.Name)
|
||||
err := DockerClient.NetworkRemove(DockerContext, network.ID)
|
||||
if err != nil {
|
||||
utils.Error("DockerNetworkCleanupRemove", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
self := os.Getenv("HOSTNAME")
|
||||
if self == "" {
|
||||
utils.Warn("Skipping zombie network cleanup because not a docker cosmos container")
|
||||
continue
|
||||
}
|
||||
|
||||
utils.Debug("Checking self name: " + self)
|
||||
utils.Debug("Checking non-empty network: " + network.Name)
|
||||
|
||||
containsCosmos := false
|
||||
for _, container := range network.Containers {
|
||||
utils.Debug("Checking name: " + container.Name)
|
||||
if(container.Name == self) {
|
||||
containsCosmos = true
|
||||
}
|
||||
utils.Error("[DOCKER] Error pruning images", err)
|
||||
}
|
||||
|
||||
if(containsCosmos) {
|
||||
// docker inspect self
|
||||
selfContainer, err := DockerClient.ContainerInspect(DockerContext, self)
|
||||
if err != nil {
|
||||
utils.Error("NetworkCleanUpInspectSelf", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// check if self is network_mode to this network
|
||||
if(string(selfContainer.HostConfig.NetworkMode) == network.Name) {
|
||||
utils.Warn("Skipping network cleanup because self is network_mode to this network")
|
||||
continue
|
||||
}
|
||||
|
||||
utils.Log("Disconnecting and removing zombie network: " + network.Name)
|
||||
err = DockerClient.NetworkDisconnect(DockerContext, network.ID, self, true)
|
||||
if err != nil {
|
||||
utils.Error("DockerNetworkCleanupDisconnect", err)
|
||||
continue
|
||||
}
|
||||
err = DockerClient.NetworkRemove(DockerContext, network.ID)
|
||||
if err != nil {
|
||||
utils.Error("DockerNetworkCleanupRemove", err)
|
||||
}
|
||||
}
|
||||
utils.Log("Pruned images: " + fmt.Sprintf("%v", report.ImagesDeleted))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ type SmartShieldPolicy struct {
|
||||
|
||||
type DockerConfig struct {
|
||||
SkipPruneNetwork bool
|
||||
SkipPruneImages bool
|
||||
DefaultDataPath string
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user