cp
This commit is contained in:
parent
d68f9df66f
commit
53db1b883d
10 changed files with 121 additions and 30 deletions
|
@ -6,6 +6,10 @@
|
|||
- New color slider with reset buttons
|
||||
- Fixed blinking modals issues
|
||||
- Added lazyloading to URL and Servapp pages images
|
||||
- Added a button in the config page to easily download the docker backup
|
||||
- Improve display or icons [fixes #121]
|
||||
- Refactored Mongo connection code [fixes #111]
|
||||
- Forward simultaneously TCP and UDP [fixes #122]
|
||||
|
||||
## Version 0.11.3
|
||||
- Fix missing even subscriber on export
|
||||
|
|
|
@ -83,6 +83,15 @@ async function addRoute(newRoute: Route): Promise<void> {
|
|||
return rawUpdateRoute("", 'add', newRoute);
|
||||
}
|
||||
|
||||
function getBackup() {
|
||||
return wrap(fetch('/cosmos/api/get-backup', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
export {
|
||||
get,
|
||||
set,
|
||||
|
@ -94,4 +103,5 @@ export {
|
|||
deleteRoute,
|
||||
addRoute,
|
||||
canSendEmail,
|
||||
getBackup,
|
||||
};
|
|
@ -1,28 +1,41 @@
|
|||
import { Button } from "@mui/material";
|
||||
|
||||
export const DownloadFile = ({ filename, content, label }) => {
|
||||
const downloadFile = () => {
|
||||
// Create a blob with the content
|
||||
const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
|
||||
export const DownloadFile = ({ filename, content, contentGetter, label }) => {
|
||||
const downloadFile = async () => {
|
||||
// Get the content
|
||||
if (contentGetter) {
|
||||
try {
|
||||
content = await contentGetter();
|
||||
if(typeof content !== "string") {
|
||||
content = JSON.stringify(content, null, 2);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a link element
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
// Create a blob with the content
|
||||
const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
|
||||
|
||||
// Append the link to the document (needed for Firefox)
|
||||
document.body.appendChild(link);
|
||||
// Create a link element
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
|
||||
// Simulate a click to start the download
|
||||
link.click();
|
||||
// Append the link to the document (needed for Firefox)
|
||||
document.body.appendChild(link);
|
||||
|
||||
// Cleanup the DOM by removing the link element
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
// Simulate a click to start the download
|
||||
link.click();
|
||||
|
||||
return (
|
||||
<Button onClick={downloadFile}>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
// Cleanup the DOM by removing the link element
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button onClick={downloadFile}>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
}
|
|
@ -33,6 +33,7 @@ import { SliderPicker
|
|||
import {SetPrimaryColor, SetSecondaryColor} from '../../../App';
|
||||
import { useClientInfos } from '../../../utils/hooks';
|
||||
import ConfirmModal from '../../../components/confirmModal';
|
||||
import { DownloadFile } from '../../../api/downloadButton';
|
||||
|
||||
const ConfigManagement = () => {
|
||||
const [config, setConfig] = React.useState(null);
|
||||
|
@ -77,6 +78,13 @@ const ConfigManagement = () => {
|
|||
}}
|
||||
label={'Purge Metrics Dashboard'}
|
||||
content={'Are you sure you want to purge all the metrics data from the dashboards?'} />
|
||||
|
||||
<DownloadFile
|
||||
filename={'backup.cosmos-compose.json'}
|
||||
label={'Download Docker Backup'}
|
||||
contentGetter={API.config.getBackup}
|
||||
/>
|
||||
|
||||
</Stack>
|
||||
|
||||
{config && <>
|
||||
|
|
|
@ -167,11 +167,12 @@ const _MiniPlotComponent = ({metrics, labels}) => {
|
|||
<Stack direction='column' justifyContent={'center'} alignItems={'center'} spacing={0} style={{
|
||||
width: '60px',
|
||||
}}>
|
||||
<div style={{
|
||||
{dataMetric.Values.length && <div style={{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '110%',
|
||||
whiteSpace: 'nowrap',
|
||||
}}>{formaters[di](dataMetric.Values[dataMetric.Values.length - 1].Value)}</div>
|
||||
}
|
||||
<div>
|
||||
<div style={{
|
||||
display: 'inline-block',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Alert, Checkbox, Chip, CircularProgress, Stack, Typography, useMediaQuery } from '@mui/material';
|
||||
import MainCard from '../../../components/MainCard';
|
||||
import { ContainerOutlined, DesktopOutlined, InfoCircleOutlined, NodeExpandOutlined, PlayCircleOutlined, PlusCircleOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
import { ContainerOutlined, DashboardOutlined, DesktopOutlined, InfoCircleOutlined, NodeExpandOutlined, PlayCircleOutlined, PlusCircleOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
import { getFaviconURL, getContainersRoutes } from '../../../utils/routes';
|
||||
import HostChip from '../../../components/hostChip';
|
||||
import ExposeModal from '../exposeModal';
|
||||
|
@ -169,8 +169,8 @@ const ContainerOverview = ({ containerInfo, config, refresh, updatesAvailable, s
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
<strong><NodeExpandOutlined /> Monitoring</strong>
|
||||
<div style={{ width: '90%' }}>
|
||||
<strong><DashboardOutlined /> Monitoring</strong>
|
||||
<div style={{ width: '96%' }}>
|
||||
<MiniPlotComponent metrics={[
|
||||
"cosmos.system.docker.cpu." + Name.replace('/', ''),
|
||||
"cosmos.system.docker.ram." + Name.replace('/', ''),
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"net/http"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
)
|
||||
|
||||
|
@ -50,3 +51,43 @@ func ConfigApiGet(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
func BackupFileApiGet(w http.ResponseWriter, req *http.Request) {
|
||||
if utils.AdminOnly(w, req) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if req.Method == "GET" {
|
||||
// read file
|
||||
path := utils.CONFIGFOLDER + "backup.cosmos-compose.json"
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
utils.Error("BackupFileApiGet: Error opening file", err)
|
||||
utils.HTTPError(w, "Error opening file", http.StatusInternalServerError, "HTTP002")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// read content
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
utils.Error("BackupFileApiGet: Error reading file content", err)
|
||||
utils.HTTPError(w, "Error reading file content", http.StatusInternalServerError, "HTTP003")
|
||||
return
|
||||
}
|
||||
|
||||
// set the content type header, so that the client knows it's receiving a JSON file
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err = w.Write(content)
|
||||
if err != nil {
|
||||
utils.Error("BackupFileApiGet: Error writing to response", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
utils.Error("BackupFileApiGet: Method not allowed " + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -553,12 +553,16 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
|||
|
||||
port, protocol := portdef, portStuff[1]
|
||||
|
||||
if protocol == "" {
|
||||
protocol = "tcp"
|
||||
}
|
||||
|
||||
nextPort := strings.Split(port, ":")
|
||||
hostPort, contPort := nextPort[0], nextPort[1]
|
||||
|
||||
contPort = contPort + "/" + protocol
|
||||
|
||||
if hostPortsBound[hostPort] {
|
||||
if hostPortsBound[hostPort + "/" + protocol] {
|
||||
utils.Warn("Port " + hostPort + " already bound, skipping")
|
||||
continue
|
||||
}
|
||||
|
@ -583,7 +587,7 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
|
|||
// Mark the container port as exposed
|
||||
containerConfig.ExposedPorts[nat.Port(contPort)] = struct{}{}
|
||||
|
||||
hostPortsBound[hostPort] = true
|
||||
hostPortsBound[hostPort + "/" + protocol] = true
|
||||
}
|
||||
|
||||
// Create missing folders for bind mounts
|
||||
|
|
|
@ -332,6 +332,8 @@ func InitServer() *mux.Router {
|
|||
srapi.HandleFunc("/api/background", UploadBackground)
|
||||
srapi.HandleFunc("/api/background/{ext}", GetBackground)
|
||||
|
||||
srapi.HandleFunc("/api/get-backup", configapi.BackupFileApiGet)
|
||||
|
||||
srapi.HandleFunc("/api/constellation/devices", constellation.ConstellationAPIDevices)
|
||||
srapi.HandleFunc("/api/constellation/restart", constellation.API_Restart)
|
||||
srapi.HandleFunc("/api/constellation/reset", constellation.API_Reset)
|
||||
|
|
|
@ -7,27 +7,35 @@ import (
|
|||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
"go.mongodb.org/mongo-driver/mongo/writeconcern"
|
||||
)
|
||||
|
||||
|
||||
var client *mongo.Client
|
||||
|
||||
func DB() error {
|
||||
if(GetBaseMainConfig().DisableUserManagement) {
|
||||
if(GetMainConfig().DisableUserManagement) {
|
||||
return errors.New("User Management is disabled")
|
||||
}
|
||||
|
||||
uri := GetBaseMainConfig().MongoDB + "/?retryWrites=true&w=majority"
|
||||
|
||||
mongoURL := GetMainConfig().MongoDB
|
||||
|
||||
if(client != nil && client.Ping(context.TODO(), readpref.Primary()) == nil) {
|
||||
return nil
|
||||
}
|
||||
|
||||
Log("(Re) Connecting to the database...")
|
||||
|
||||
if mongoURL == "" {
|
||||
return errors.New("MongoDB URL is not set, cannot connect to the database.")
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
client, err = mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
|
||||
opts := options.Client().ApplyURI(mongoURL).SetRetryWrites(true).SetWriteConcern(writeconcern.New(writeconcern.WMajority()))
|
||||
|
||||
client, err = mongo.Connect(context.TODO(), opts)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue