[release] v0.4.0-unstable6
This commit is contained in:
parent
6a8e97b242
commit
08d7dbbe4e
|
@ -66,3 +66,7 @@
|
||||||
.darken {
|
.darken {
|
||||||
filter: brightness(0.5);
|
filter: brightness(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MuiAlert-icon {
|
||||||
|
align-items: center;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IconButton, Tooltip } from '@mui/material';
|
import { IconButton, Tooltip } from '@mui/material';
|
||||||
import { CloseSquareOutlined, DeleteOutlined, PauseCircleOutlined, PlaySquareOutlined, ReloadOutlined, RollbackOutlined, StopOutlined, UpCircleOutlined } from '@ant-design/icons';
|
import { CheckCircleOutlined, CloseSquareOutlined, DeleteOutlined, PauseCircleOutlined, PlaySquareOutlined, ReloadOutlined, RollbackOutlined, StopOutlined, UpCircleOutlined } from '@ant-design/icons';
|
||||||
import * as API from '../../api';
|
import * as API from '../../api';
|
||||||
|
|
||||||
const GetActions = ({
|
const GetActions = ({
|
||||||
|
@ -9,6 +9,8 @@ const GetActions = ({
|
||||||
refreshServeApps,
|
refreshServeApps,
|
||||||
setIsUpdatingId
|
setIsUpdatingId
|
||||||
}) => {
|
}) => {
|
||||||
|
const [confirmDelete, setConfirmDelete] = React.useState(false);
|
||||||
|
|
||||||
const doTo = (action) => {
|
const doTo = (action) => {
|
||||||
setIsUpdatingId(Id, true);
|
setIsUpdatingId(Id, true);
|
||||||
API.docker.manageContainer(Id, action).then((res) => {
|
API.docker.manageContainer(Id, action).then((res) => {
|
||||||
|
@ -76,8 +78,12 @@ const GetActions = ({
|
||||||
{
|
{
|
||||||
t: 'Delete',
|
t: 'Delete',
|
||||||
if: ['exited', 'created'],
|
if: ['exited', 'created'],
|
||||||
e: <IconButton onClick={() => {doTo('remove')}} color="error" size='large'>
|
e: <IconButton onClick={() => {
|
||||||
<DeleteOutlined />
|
if(confirmDelete) doTo('remove')
|
||||||
|
else setConfirmDelete(true);
|
||||||
|
}} color="error" size='large'>
|
||||||
|
{confirmDelete ? <CheckCircleOutlined />
|
||||||
|
: <DeleteOutlined />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { Button, Stack, Grid, MenuItem, TextField, IconButton, FormHelperText, CircularProgress, useTheme } from '@mui/material';
|
import { Button, Stack, Grid, MenuItem, TextField, IconButton, FormHelperText, CircularProgress, useTheme, Alert } from '@mui/material';
|
||||||
import MainCard from '../../../components/MainCard';
|
import MainCard from '../../../components/MainCard';
|
||||||
import { CosmosCheckbox, CosmosFormDivider, CosmosInputText, CosmosSelect }
|
import { CosmosCheckbox, CosmosFormDivider, CosmosInputText, CosmosSelect }
|
||||||
from '../../config/users/formShortcuts';
|
from '../../config/users/formShortcuts';
|
||||||
|
@ -12,13 +12,6 @@ import { NetworksColumns } from '../networks';
|
||||||
import NewNetworkButton from '../createNetwork';
|
import NewNetworkButton from '../createNetwork';
|
||||||
|
|
||||||
const NetworkContainerSetup = ({ config, containerInfo, refresh }) => {
|
const NetworkContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
const restartPolicies = [
|
|
||||||
['no', 'No Restart'],
|
|
||||||
['always', 'Always Restart'],
|
|
||||||
['on-failure', 'Restart On Failure'],
|
|
||||||
['unless-stopped', 'Restart Unless Stopped'],
|
|
||||||
];
|
|
||||||
|
|
||||||
const [networks, setNetworks] = React.useState([]);
|
const [networks, setNetworks] = React.useState([]);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isDark = theme.palette.mode === 'dark';
|
const isDark = theme.palette.mode === 'dark';
|
||||||
|
@ -40,13 +33,13 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
|
|
||||||
const connect = (network) => {
|
const connect = (network) => {
|
||||||
setNetworks(null);
|
setNetworks(null);
|
||||||
return API.docker.attachNetwork(containerInfo.Id, network).then(() => {
|
return API.docker.attachNetwork(containerInfo.Name.replace('/', ''), network).then(() => {
|
||||||
refreshAll();
|
refreshAll();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const disconnect = (network) => {
|
const disconnect = (network) => {
|
||||||
return API.docker.detachNetwork(containerInfo.Id, network).then(() => {
|
return API.docker.detachNetwork(containerInfo.Name.replace('/', ''), network).then(() => {
|
||||||
refreshAll();
|
refreshAll();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -94,18 +87,20 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setStatus({ success: true });
|
setStatus({ success: true });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
refresh && refresh();
|
||||||
}
|
}
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
setStatus({ success: false });
|
setStatus({ success: false });
|
||||||
setErrors({ submit: err.message });
|
setErrors({ submit: err.message });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
refresh && refresh();
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(formik) => (
|
{(formik) => (
|
||||||
<form noValidate onSubmit={formik.handleSubmit}>
|
<form noValidate onSubmit={formik.handleSubmit}>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<MainCard title={'Exposed Ports'}>
|
<MainCard title={'Ports'}>
|
||||||
<Grid container spacing={4}>
|
<Grid container spacing={4}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
{formik.values.ports.map((port, idx) => (
|
{formik.values.ports.map((port, idx) => (
|
||||||
|
@ -209,7 +204,30 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</MainCard>
|
</MainCard>
|
||||||
<MainCard title={'Connected Networks'}>
|
<MainCard title={'Networks'}>
|
||||||
|
<Stack spacing={2}>
|
||||||
|
{networks && <Stack spacing={2}>
|
||||||
|
{Object.keys(containerInfo.NetworkSettings.Networks).map((networkName) => {
|
||||||
|
const network = networks.find((n) => n.Name === networkName);
|
||||||
|
if (!network) {
|
||||||
|
return <Alert severity="error">
|
||||||
|
You are connected to a network that has been removed: <strong>{networkName}</strong>.
|
||||||
|
Either re-create it or
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: '10px' }}
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
disconnect(networkName);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Disconnect It
|
||||||
|
</Button>
|
||||||
|
</Alert>
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Stack>}
|
||||||
|
|
||||||
{networks && <PrettyTableView
|
{networks && <PrettyTableView
|
||||||
data={networks}
|
data={networks}
|
||||||
buttons={[
|
buttons={[
|
||||||
|
@ -252,6 +270,7 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
</center>
|
</center>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</Stack>
|
||||||
</MainCard>
|
</MainCard>
|
||||||
</Stack>
|
</Stack>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { DeleteOutlined, PlusCircleOutlined } from '@ant-design/icons';
|
||||||
import * as API from '../../../api';
|
import * as API from '../../../api';
|
||||||
import { LoadingButton } from '@mui/lab';
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
|
||||||
const DockerContainerSetup = ({config, containerInfo}) => {
|
const DockerContainerSetup = ({config, containerInfo, refresh}) => {
|
||||||
const restartPolicies = [
|
const restartPolicies = [
|
||||||
['no', 'No Restart'],
|
['no', 'No Restart'],
|
||||||
['always', 'Always Restart'],
|
['always', 'Always Restart'],
|
||||||
|
@ -66,6 +66,7 @@ const DockerContainerSetup = ({config, containerInfo}) => {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setStatus({ success: true });
|
setStatus({ success: true });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
refresh && refresh();
|
||||||
}
|
}
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
setStatus({ success: false });
|
setStatus({ success: false });
|
||||||
|
|
|
@ -24,16 +24,16 @@ const VolumeContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
const isDark = theme.palette.mode === 'dark';
|
const isDark = theme.palette.mode === 'dark';
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
API.docker.networkList().then((res) => {
|
API.docker.volumeList().then((res) => {
|
||||||
setVolumes(res.data);
|
setVolumes(res.data.Volumes);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const refreshAll = () => {
|
const refreshAll = () => {
|
||||||
setVolumes(null);
|
setVolumes(null);
|
||||||
refresh().then(() => {
|
refresh().then(() => {
|
||||||
API.docker.networkList().then((res) => {
|
API.docker.volumeList().then((res) => {
|
||||||
setVolumes(res.data);
|
setVolumes(res.data.Volumes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -75,11 +75,13 @@ const VolumeContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setStatus({ success: true });
|
setStatus({ success: true });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
refresh && refresh();
|
||||||
}
|
}
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
setStatus({ success: false });
|
setStatus({ success: false });
|
||||||
setErrors({ submit: err.message });
|
setErrors({ submit: err.message });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
refresh && refresh();
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -193,7 +195,6 @@ const VolumeContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
{
|
{
|
||||||
title: '',
|
title: '',
|
||||||
field: (r) => {
|
field: (r) => {
|
||||||
console.log(r);
|
|
||||||
return (<Button
|
return (<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
@ -208,7 +209,7 @@ const VolumeContainerSetup = ({ config, containerInfo, refresh }) => {
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>}
|
/>}
|
||||||
{!volumes && (<div style={{ height: '550px' }}>
|
{!volumes && (<div style={{ height: '100px' }}>
|
||||||
<center>
|
<center>
|
||||||
<br />
|
<br />
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
|
|
|
@ -106,6 +106,9 @@ const NetworkManagementList = () => {
|
||||||
API.docker.networkDelete(r.Id).then(() => {
|
API.docker.networkDelete(r.Id).then(() => {
|
||||||
refresh();
|
refresh();
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
}).catch(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
refresh();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setTryDelete(r.Id);
|
setTryDelete(r.Id);
|
||||||
|
|
|
@ -152,7 +152,7 @@ const ServeApps = () => {
|
||||||
|
|
||||||
<Grid2 container spacing={2}>
|
<Grid2 container spacing={2}>
|
||||||
{serveApps && serveApps.filter(app => search.length < 2 || app.Names[0].toLowerCase().includes(search.toLowerCase())).map((app) => {
|
{serveApps && serveApps.filter(app => search.length < 2 || app.Names[0].toLowerCase().includes(search.toLowerCase())).map((app) => {
|
||||||
return <Grid2 style={gridAnim} xs={12} sm={6} md={6} lg={6} xl={4}>
|
return <Grid2 style={gridAnim} xs={12} sm={6} md={6} lg={6} xl={4} key={app.Id} item>
|
||||||
<Item>
|
<Item>
|
||||||
<Stack justifyContent='space-around' direction="column" spacing={2} padding={2} divider={<Divider orientation="horizontal" flexItem />}>
|
<Stack justifyContent='space-around' direction="column" spacing={2} padding={2} divider={<Divider orientation="horizontal" flexItem />}>
|
||||||
<Stack direction="column" spacing={0} alignItems="flex-start">
|
<Stack direction="column" spacing={0} alignItems="flex-start">
|
||||||
|
|
|
@ -99,6 +99,9 @@ const VolumeManagementList = () => {
|
||||||
API.docker.volumeDelete(r.Name).then(() => {
|
API.docker.volumeDelete(r.Name).then(() => {
|
||||||
refresh();
|
refresh();
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
}).catch(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
refresh();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setTryDelete(r.Name);
|
setTryDelete(r.Name);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cosmos-server",
|
"name": "cosmos-server",
|
||||||
"version": "0.4.0-unstable5",
|
"version": "0.4.0-unstable6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "test-server.js",
|
"main": "test-server.js",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -25,11 +25,19 @@ func ManageContainerRoute(w http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
containerName := utils.Sanitize(vars["containerId"])
|
containerName := utils.Sanitize(vars["containerId"])
|
||||||
// stop, start, restart, kill, remove, pause, unpause, recreate
|
// stop, start, restart, kill, remove, pause, unpause, recreate
|
||||||
action := utils.Sanitize(vars["action"])
|
action := utils.Sanitize(vars["action"])
|
||||||
|
|
||||||
|
if os.Getenv("HOSTNAME") != "" && (action == "recreate" || action == "update") && containerName == os.Getenv("HOSTNAME") {
|
||||||
|
utils.Error("ManageContainer - cannot recreate/update self", nil)
|
||||||
|
utils.HTTPError(w, "Cannot recreate/update self", http.StatusBadRequest, "DS003")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
utils.Log("ManageContainer " + containerName)
|
utils.Log("ManageContainer " + containerName)
|
||||||
|
|
||||||
if req.Method == "GET" {
|
if req.Method == "GET" {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/azukaar/cosmos-server/src/utils"
|
"github.com/azukaar/cosmos-server/src/utils"
|
||||||
|
@ -157,6 +158,12 @@ func DetachNetwork(w http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if os.Getenv("HOSTNAME") != "" && networkID == "bridge" && containerID == os.Getenv("HOSTNAME") {
|
||||||
|
utils.Error("DetachNetwork - Cannot disconnect self from bridge", nil)
|
||||||
|
utils.HTTPError(w, "Cannot disconnect self from bridge", http.StatusBadRequest, "DS003")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := DockerClient.NetworkDisconnect(context.Background(), networkID, containerID, true)
|
err := DockerClient.NetworkDisconnect(context.Background(), networkID, containerID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Error("DetachNetwork: Error while detaching network", err)
|
utils.Error("DetachNetwork: Error while detaching network", err)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package docker
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/azukaar/cosmos-server/src/utils"
|
"github.com/azukaar/cosmos-server/src/utils"
|
||||||
|
|
||||||
|
@ -18,6 +19,12 @@ func SecureContainerRoute(w http.ResponseWriter, req *http.Request) {
|
||||||
containerName := utils.Sanitize(vars["containerId"])
|
containerName := utils.Sanitize(vars["containerId"])
|
||||||
status := utils.Sanitize(vars["status"])
|
status := utils.Sanitize(vars["status"])
|
||||||
|
|
||||||
|
if os.Getenv("HOSTNAME") != "" && containerName == os.Getenv("HOSTNAME") {
|
||||||
|
utils.Error("SecureContainerRoute - Cannot force secure self", nil)
|
||||||
|
utils.HTTPError(w, "Cannot force secure self", http.StatusBadRequest, "DS003")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if(req.Method == "GET") {
|
if(req.Method == "GET") {
|
||||||
container, err := DockerClient.ContainerInspect(DockerContext, containerName)
|
container, err := DockerClient.ContainerInspect(DockerContext, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package docker
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/azukaar/cosmos-server/src/utils"
|
"github.com/azukaar/cosmos-server/src/utils"
|
||||||
containerType "github.com/docker/docker/api/types/container"
|
containerType "github.com/docker/docker/api/types/container"
|
||||||
|
@ -38,6 +39,12 @@ func UpdateContainerRoute(w http.ResponseWriter, req *http.Request) {
|
||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
containerName := utils.Sanitize(vars["containerId"])
|
containerName := utils.Sanitize(vars["containerId"])
|
||||||
|
|
||||||
|
if os.Getenv("HOSTNAME") != "" && containerName == os.Getenv("HOSTNAME") {
|
||||||
|
utils.Error("SecureContainerRoute - Cannot update self", nil)
|
||||||
|
utils.HTTPError(w, "Cannot update self", http.StatusBadRequest, "DS003")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
container, err := DockerClient.ContainerInspect(DockerContext, containerName)
|
container, err := DockerClient.ContainerInspect(DockerContext, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Error("UpdateContainer", err)
|
utils.Error("UpdateContainer", err)
|
||||||
|
|
|
@ -25,11 +25,9 @@ func main() {
|
||||||
docker.BootstrapAllContainersFromTags()
|
docker.BootstrapAllContainersFromTags()
|
||||||
|
|
||||||
version, err := docker.DockerClient.ServerVersion(context.Background())
|
version, err := docker.DockerClient.ServerVersion(context.Background())
|
||||||
if err != nil {
|
if err == nil {
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.Log("Docker API version: " + version.APIVersion)
|
utils.Log("Docker API version: " + version.APIVersion)
|
||||||
|
}
|
||||||
|
|
||||||
StartServer()
|
StartServer()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue