[release] v0.12.0-unstable13

This commit is contained in:
Yann Stepienik 2023-10-29 13:01:12 +00:00
parent 5c1b7e5d74
commit af4ecbef41
12 changed files with 289 additions and 94 deletions

View file

@ -1,6 +1,7 @@
## Version 0.12.0 ## Version 0.12.0
- New Dashboard - New Dashboard
- New metrics gathering system - New metrics gathering system
- Integrated a new docker-less mode of functioning for networking
- Added Button to force reset HTTPS cert in settings - Added Button to force reset HTTPS cert in settings
## Version 0.11.3 ## Version 0.11.3

View file

@ -46,12 +46,19 @@ function toUTC(date, time) {
return formatDate(now, time); return formatDate(now, time);
} }
const PlotComponent = ({ title, data, defaultSlot = 'latest' }) => { const PlotComponent = ({ title, data, SimpleDesign, withSelector, defaultSlot = 'latest' }) => {
const [slot, setSlot] = useState(defaultSlot); const [slot, setSlot] = useState(defaultSlot);
const theme = useTheme(); const theme = useTheme();
const { primary, secondary } = theme.palette.text; const { primary, secondary } = theme.palette.text;
const line = theme.palette.divider; const line = theme.palette.divider;
const [series, setSeries] = useState([]); const [series, setSeries] = useState([]);
const [selected, setSelected] = useState(withSelector ? data.findIndex((d) => d.Key === withSelector)
: 0);
const isDark = theme.palette.mode === 'dark';
const backColor = isDark ? '0,0,0' : '255,255,255';
const textColor = isDark ? 'white' : 'dark';
// chart options // chart options
const areaChartOptions = { const areaChartOptions = {
@ -99,8 +106,12 @@ const PlotComponent = ({ title, data, defaultSlot = 'latest' }) => {
} }
} }
let toProcess = data;
if(withSelector) {
toProcess = data.filter((d, id) => id === selected);
}
const dataSeries = []; const dataSeries = [];
data.forEach((serie) => { toProcess.forEach((serie) => {
dataSeries.push({ dataSeries.push({
name: serie.Label, name: serie.Label,
dataAxis: xAxis.map((date) => { dataAxis: xAxis.map((date) => {
@ -131,26 +142,27 @@ const PlotComponent = ({ title, data, defaultSlot = 'latest' }) => {
: xAxis, : xAxis,
labels: { labels: {
style: { style: {
fontSize: slot === 'latest' ? '0' : '11px', fontSize: (slot === 'latest' || SimpleDesign) ? '0' : '11px',
} }
}, },
axisBorder: { axisBorder: {
show: true, show: !SimpleDesign,
color: line color: line
}, },
tickAmount: xAxis.length, tickAmount: xAxis.length,
}, },
yaxis: data.map((thisdata, ida) => ({ yaxis: toProcess.map((thisdata, ida) => ({
opposite: ida === 1, opposite: ida === 1,
labels: { labels: {
style: { style: {
colors: [secondary] colors: [secondary],
fontSize: '11px',
}, },
formatter: FormaterForMetric(thisdata) formatter: FormaterForMetric(thisdata)
}, },
title: { title: {
text: thisdata.Label, text: SimpleDesign ? '' : thisdata.Label,
} }
})), })),
grid: { grid: {
@ -167,16 +179,34 @@ const PlotComponent = ({ title, data, defaultSlot = 'latest' }) => {
data: serie.dataAxis data: serie.dataAxis
} }
})); }));
}, [slot, data]); }, [slot, data, selected]);
return <Grid item xs={12} md={7} lg={8}> return <Grid item xs={12} md={7} lg={8} >
<Grid container alignItems="center" justifyContent="space-between"> <Grid container alignItems="center" justifyContent="space-between">
<Grid item> <Grid item>
<Typography variant="h5">{title}</Typography> <Typography variant="h5">{title}</Typography>
</Grid> </Grid>
<Grid item> <Grid item >
<Stack direction="row" alignItems="center" spacing={0}> <Stack direction="row" alignItems="center" spacing={0}>
{withSelector &&
<div style={{ marginRight: 15 }}>
<TextField
id="standard-select-currency"
size="small"
select
value={selected}
onChange={(e) => setSelected(e.target.value)}
sx={{ '& .MuiInputBase-input': { py: 0.5, fontSize: '0.875rem', } }}
>
{data.map((option, i) => (
<MenuItem key={i} value={i}>
{option.Label}
</MenuItem>
))}
</TextField></div>}
<Button <Button
size="small" size="small"
onClick={() => setSlot('latest')} onClick={() => setSlot('latest')}
@ -204,7 +234,7 @@ const PlotComponent = ({ title, data, defaultSlot = 'latest' }) => {
</Stack> </Stack>
</Grid> </Grid>
</Grid> </Grid>
<MainCard content={false} sx={{ mt: 1.5 }}> <MainCard content={false} sx={{ mt: 1.5 }} >
<Box sx={{ pt: 1, pr: 2 }}> <Box sx={{ pt: 1, pr: 2 }}>
<ReactApexChart options={options} series={series} type="area" height={450} /> <ReactApexChart options={options} series={series} type="area" height={450} />
</Box> </Box>

View file

@ -98,7 +98,7 @@ function OrderTableHead({ order, orderBy, headCells }) {
); );
} }
const TableComponent = ({ title, data, defaultSlot = 'latest' }) => { const TableComponent = ({ title, data, displayMax, render, defaultSlot = 'latest' }) => {
const [slot, setSlot] = useState(defaultSlot); const [slot, setSlot] = useState(defaultSlot);
const theme = useTheme(); const theme = useTheme();
const { primary, secondary } = theme.palette.text; const { primary, secondary } = theme.palette.text;
@ -121,15 +121,17 @@ const TableComponent = ({ title, data, defaultSlot = 'latest' }) => {
heads[cat] = true; heads[cat] = true;
let formatter = FormaterForMetric(item); let formatter = FormaterForMetric(item, displayMax);
if(!fnrows.find((row) => row.name === name)) { if(!fnrows.find((row) => row.name === name)) {
fnrows.push({ fnrows.push({
name, name,
[cat]: formatter(v.Value) [cat]: render ? render(item, v.Value, formatter(v.Value)) : formatter(v.Value),
["__" + cat]: v.Value
}); });
} else { } else {
fnrows.find((row) => row.name === name)[cat] = formatter(v.Value); fnrows.find((row) => row.name === name)[cat] = render ? render(item, v.Value, formatter(v.Value)) : formatter(v.Value)
fnrows.find((row) => row.name === name)["__" + cat] = v.Value
} }
}); });
@ -137,7 +139,8 @@ const TableComponent = ({ title, data, defaultSlot = 'latest' }) => {
fnrows = fnrows.filter((row) => { fnrows = fnrows.filter((row) => {
let flag = false; let flag = false;
Object.keys(row).forEach((key) => { Object.keys(row).forEach((key) => {
if(key !== 'name' && row[key] != 0) { if(key !== 'name' && row["__" + key]) {
console.log(key, row["__" + key])
flag = true; flag = true;
} }
}); });
@ -212,7 +215,8 @@ const TableComponent = ({ title, data, defaultSlot = 'latest' }) => {
position: 'relative', position: 'relative',
display: 'block', display: 'block',
maxWidth: '100%', maxWidth: '100%',
'& td, & th': { whiteSpace: 'nowrap' } '& td, & th': { whiteSpace: 'nowrap' },
maxHeight: '474px'
}} }}
> >
<Table <Table
@ -227,7 +231,7 @@ const TableComponent = ({ title, data, defaultSlot = 'latest' }) => {
}} }}
> >
<OrderTableHead headCells={headCells} order={order} orderBy={orderBy} /> <OrderTableHead headCells={headCells} order={order} orderBy={orderBy} />
<TableBody> <TableBody style={{height:'409px', overflow: 'auto'}}>
{stableSort(rows, getComparator(order, orderBy)).map((row, index) => { {stableSort(rows, getComparator(order, orderBy)).map((row, index) => {
const isItemSelected = false // isSelected(row.trackingNo); const isItemSelected = false // isSelected(row.trackingNo);
const labelId = `enhanced-table-checkbox-${index}`; const labelId = `enhanced-table-checkbox-${index}`;

View file

@ -1,11 +1,5 @@
export const FormaterForMetric = (metric) => { export const simplifyNumber = (num) => {
console.log(metric)
return (num) => {
if(!num) return 0; if(!num) return 0;
if(metric.Scale)
num /= metric.Scale;
if (Math.abs(num) >= 1e12) { if (Math.abs(num) >= 1e12) {
return (num / 1e12).toFixed(1) + 'T'; // Convert to Millions return (num / 1e12).toFixed(1) + 'T'; // Convert to Millions
@ -18,5 +12,23 @@ export const FormaterForMetric = (metric) => {
} else { } else {
return num.toString(); return num.toString();
} }
}
export const FormaterForMetric = (metric, displayMax) => {
console.log(metric)
return (num) => {
if(!num) return 0;
if(metric.Scale)
num /= metric.Scale;
num = simplifyNumber(num);
if(displayMax && metric.Max) {
num += ` / ${simplifyNumber(metric.Max)}`
}
return num;
} }
} }

View file

@ -16,7 +16,8 @@ import {
Stack, Stack,
TextField, TextField,
Typography, Typography,
Alert Alert,
LinearProgress
} from '@mui/material'; } from '@mui/material';
// project import // project import
@ -40,6 +41,7 @@ import * as API from '../../api';
import AnimateButton from '../../components/@extended/AnimateButton'; import AnimateButton from '../../components/@extended/AnimateButton';
import PlotComponent from './components/plot'; import PlotComponent from './components/plot';
import TableComponent from './components/table'; import TableComponent from './components/table';
import { HomeBackground, TransparentHeader } from '../home';
// avatar style // avatar style
const avatarSX = { const avatarSX = {
@ -108,54 +110,12 @@ const DashboardDefault = () => {
return ( return (
<> <>
{/* <HomeBackground status={coStatus} />
<TransparentHeader /> */}
<IsLoggedIn /> <IsLoggedIn />
<div> {metrics && <div style={{marginTop: '30px', zIndex:2, position: 'relative'}}>
<Stack spacing={1}> <Grid container rowSpacing={4.5} columnSpacing={2.75} >
{coStatus && !coStatus.database && ( {/*
<Alert severity="error">
No Database is setup for Cosmos! User Management and Authentication will not work.<br />
You can either setup the database, or disable user management in the configuration panel.<br />
</Alert>
)}
{coStatus && coStatus.letsencrypt && (
<Alert severity="error">
You have enabled Let's Encrypt for automatic HTTPS Certificate. You need to provide the configuration with an email address to use for Let's Encrypt in the configs.
</Alert>
)}
{coStatus && coStatus.newVersionAvailable && (
<Alert severity="warning">
A new version of Cosmos is available! Please update to the latest version to get the latest features and bug fixes.
</Alert>
)}
{coStatus && coStatus.needsRestart && (
<Alert severity="warning">
You have made changes to the configuration that require a restart to take effect. Please restart Cosmos to apply the changes.
</Alert>
)}
{coStatus && coStatus.domain && (
<Alert severity="error">
You are using localhost or 0.0.0.0 as a hostname in the configuration. It is recommended that you use a domain name instead.
</Alert>
)}
{coStatus && !coStatus.docker && (
<Alert severity="error">
Docker is not connected! Please check your docker connection.<br/>
Did you forget to add <pre>-v /var/run/docker.sock:/var/run/docker.sock</pre> to your docker run command?<br />
if your docker daemon is running somewhere else, please add <pre>-e DOCKER_HOST=...</pre> to your docker run command.
</Alert>
)}
<Alert severity="info">Dashboard implementation currently in progress! If you want to voice your opinion on where Cosmos is going, please join us on Discord!</Alert>
</Stack>
</div>
{metrics && <div style={{marginTop: '30px'}}>
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
{/* row 1 */}
<Grid item xs={12} sx={{ mb: -2.25 }}> <Grid item xs={12} sx={{ mb: -2.25 }}>
<Typography variant="h5">Dashboard</Typography> <Typography variant="h5">Dashboard</Typography>
</Grid> </Grid>
@ -173,8 +133,8 @@ const DashboardDefault = () => {
</Grid> </Grid>
<Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} /> <Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} />
*/}
{/* row 2 */}
<PlotComponent title={'Resources'} data={[metrics["cosmos.system.cpu.0"], metrics["cosmos.system.ram"]]}/> <PlotComponent title={'Resources'} data={[metrics["cosmos.system.cpu.0"], metrics["cosmos.system.ram"]]}/>
@ -187,8 +147,26 @@ const DashboardDefault = () => {
<TableComponent title="Containers - Network" data={ <TableComponent title="Containers - Network" data={
Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.docker.net")).map((key) => metrics[key]) Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.docker.net")).map((key) => metrics[key])
}/> }/>
{/* row 3 */} <TableComponent title="Disk Usage" displayMax={true}
render={(metric, value, formattedValue) => {
return <span>
{formattedValue}
<LinearProgress variant="determinate" value={value / metric.Max * 100} />
</span>
}}
data={
Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.disk")).map((key) => metrics[key])
}/>
<PlotComponent
title={'Temperature'}
withSelector={'cosmos.system.temp.all'}
SimpleDesign
data={Object.keys(metrics).filter((key) => key.startsWith("cosmos.system.temp")).map((key) => metrics[key])}
/>
{/*
<Grid item xs={12} md={7} lg={8}> <Grid item xs={12} md={7} lg={8}>
<Grid container alignItems="center" justifyContent="space-between"> <Grid container alignItems="center" justifyContent="space-between">
<Grid item> <Grid item>
@ -227,7 +205,6 @@ const DashboardDefault = () => {
</MainCard> </MainCard>
</Grid> </Grid>
{/* row 4 */}
<Grid item xs={12} md={7} lg={8}> <Grid item xs={12} md={7} lg={8}>
<Grid container alignItems="center" justifyContent="space-between"> <Grid container alignItems="center" justifyContent="space-between">
<Grid item> <Grid item>
@ -382,6 +359,7 @@ const DashboardDefault = () => {
</Stack> </Stack>
</MainCard> </MainCard>
</Grid> </Grid>
*/}
</Grid> </Grid>
</div>} </div>}
</> </>

View file

@ -1,6 +1,6 @@
{ {
"name": "cosmos-server", "name": "cosmos-server",
"version": "0.12.0-unstable12", "version": "0.12.0-unstable13",
"description": "", "description": "",
"main": "test-server.js", "main": "test-server.js",
"bugs": { "bugs": {

View file

@ -703,18 +703,23 @@ func StatsAll() ([]ContainerStats, error) {
cpuDelta := float64(stats.CPUStats.CPUUsage.TotalUsage - stats.PreCPUStats.CPUUsage.TotalUsage) cpuDelta := float64(stats.CPUStats.CPUUsage.TotalUsage - stats.PreCPUStats.CPUUsage.TotalUsage)
systemDelta := float64(stats.CPUStats.SystemUsage - stats.PreCPUStats.SystemUsage) systemDelta := float64(stats.CPUStats.SystemUsage - stats.PreCPUStats.SystemUsage)
utils.Debug("StatsAll - CPU CPUUsage TotalUsage " + strconv.FormatUint(stats.CPUStats.CPUUsage.TotalUsage, 10)) perCore := len(stats.CPUStats.CPUUsage.PercpuUsage)
utils.Debug("StatsAll - CPU PreCPUStats TotalUsage " + strconv.FormatUint(stats.PreCPUStats.CPUUsage.TotalUsage, 10)) if perCore == 0 {
utils.Debug("StatsAll - CPU CPUUsage PercpuUsage " + strconv.Itoa(len(stats.CPUStats.CPUUsage.PercpuUsage))) perCore = 1
utils.Debug("StatsAll - CPU CPUUsage SystemUsage " + strconv.FormatUint(stats.CPUStats.SystemUsage, 10)) }
// utils.Debug("StatsAll - CPU CPUUsage TotalUsage " + strconv.FormatUint(stats.CPUStats.CPUUsage.TotalUsage, 10))
// utils.Debug("StatsAll - CPU PreCPUStats TotalUsage " + strconv.FormatUint(stats.PreCPUStats.CPUUsage.TotalUsage, 10))
// utils.Debug("StatsAll - CPU CPUUsage PercpuUsage " + strconv.Itoa(perCore))
// utils.Debug("StatsAll - CPU CPUUsage SystemUsage " + strconv.FormatUint(stats.CPUStats.SystemUsage, 10))
utils.Debug("StatsAll - CPU CPUUsage CPU Delta " + strconv.FormatFloat(cpuDelta, 'f', 6, 64)) // utils.Debug("StatsAll - CPU CPUUsage CPU Delta " + strconv.FormatFloat(cpuDelta, 'f', 6, 64))
utils.Debug("StatsAll - CPU CPUUsage System Delta " + strconv.FormatFloat(systemDelta, 'f', 6, 64)) // utils.Debug("StatsAll - CPU CPUUsage System Delta " + strconv.FormatFloat(systemDelta, 'f', 6, 64))
cpuUsage := 0.0 cpuUsage := 0.0
if systemDelta > 0 && cpuDelta > 0 { if systemDelta > 0 && cpuDelta > 0 {
cpuUsage = (cpuDelta / systemDelta) * float64(len(stats.CPUStats.CPUUsage.PercpuUsage)) * 100 cpuUsage = (cpuDelta / systemDelta) * float64(perCore) * 100
utils.Debug("StatsAll - CPU CPUUsage " + strconv.FormatFloat(cpuUsage, 'f', 6, 64)) utils.Debug("StatsAll - CPU CPUUsage " + strconv.FormatFloat(cpuUsage, 'f', 6, 64))
} else { } else {

94
src/docker/ip.go Normal file
View file

@ -0,0 +1,94 @@
package docker
import (
"fmt"
"sync"
"time"
"github.com/azukaar/cosmos-server/src/utils"
)
type Cache struct {
data map[string]cacheItem
mu sync.Mutex
}
type cacheItem struct {
ipAddress string
expires time.Time
}
func NewCache() *Cache {
return &Cache{
data: make(map[string]cacheItem),
}
}
func (c *Cache) Get(key string) (string, bool) {
c.mu.Lock()
defer c.mu.Unlock()
item, found := c.data[key]
if !found || time.Now().After(item.expires) {
if found {
delete(c.data, key)
}
return "", false
}
return item.ipAddress, true
}
func (c *Cache) Set(key string, value string, duration time.Duration) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = cacheItem{
ipAddress: value,
expires: time.Now().Add(duration),
}
}
func _getContainerIPByName(containerName string) (string, error) {
container, err := DockerClient.ContainerInspect(DockerContext, containerName)
if err != nil {
return "", err
}
// Prioritize "host"
if net, ok := container.NetworkSettings.Networks["host"]; ok && net.IPAddress != "" {
return net.IPAddress, nil
}
// Next, prioritize "bridge"
if net, ok := container.NetworkSettings.Networks["bridge"]; ok && net.IPAddress != "" {
return net.IPAddress, nil
}
// Finally, return the IP of the first network we find
for _, net := range container.NetworkSettings.Networks {
if net.IPAddress != "" {
return net.IPAddress, nil
}
}
return "", fmt.Errorf("no IP address found for container %s", containerName)
}
var cache = NewCache()
func GetContainerIPByName(containerName string) (ip string, err error) {
// Check cache first
ip, found := cache.Get(containerName)
if !found {
ip, err = _getContainerIPByName(containerName)
if err != nil {
utils.Error("Docker - Cannot get container IP", err)
return "", err
}
cache.Set(containerName, ip, 10*time.Second)
}
utils.Debug("Docker - Docker IP " + containerName + " : " + ip)
return ip, nil
}

View file

@ -42,15 +42,25 @@ func main() {
utils.Log("Docker API version: " + version.APIVersion) utils.Log("Docker API version: " + version.APIVersion)
} }
utils.Log("Starting monitoring services...")
metrics.Init() metrics.Init()
utils.Log("Starting market services...")
market.Init() market.Init()
utils.Log("Starting OpenID services...")
authorizationserver.Init() authorizationserver.Init()
utils.Log("Starting constellation services...")
constellation.InitDNS() constellation.InitDNS()
constellation.Init() constellation.Init()
utils.Log("Starting server...")
StartServer() StartServer()
} }

View file

@ -12,6 +12,7 @@ import (
"github.com/shirou/gopsutil/v3/net" "github.com/shirou/gopsutil/v3/net"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/common" "github.com/shirou/gopsutil/v3/common"
"github.com/shirou/gopsutil/v3/host"
"github.com/azukaar/cosmos-server/src/utils" "github.com/azukaar/cosmos-server/src/utils"
"github.com/azukaar/cosmos-server/src/docker" "github.com/azukaar/cosmos-server/src/docker"
@ -82,10 +83,10 @@ func GetSystemMetrics() {
// Get Network Usage // Get Network Usage
netIO, err := net.IOCountersWithContext(ctx, false) netIO, err := net.IOCountersWithContext(ctx, false)
netIOTest, _ := net.IOCountersWithContext(ctx, true) // netIOTest, _ := net.IOCountersWithContext(ctx, true)
for _, v := range netIOTest { // for _, v := range netIOTest {
utils.Debug("Metrics - Network " + v.Name + " : " + strconv.Itoa(int(v.BytesRecv)) + " / " + strconv.Itoa(int(v.BytesSent)) + " / " + strconv.Itoa(int(v.Errin + v.Errout)) + " / " + strconv.Itoa(int(v.Dropin + v.Dropout))) // utils.Debug("Metrics - Network " + v.Name + " : " + strconv.Itoa(int(v.BytesRecv)) + " / " + strconv.Itoa(int(v.BytesSent)) + " / " + strconv.Itoa(int(v.Errin + v.Errout)) + " / " + strconv.Itoa(int(v.Dropin + v.Dropout)))
} // }
PushSetMetric("system.netRx", int(netIO[0].BytesRecv), DataDef{ PushSetMetric("system.netRx", int(netIO[0].BytesRecv), DataDef{
Max: 0, Max: 0,
@ -159,6 +160,11 @@ func GetSystemMetrics() {
for _, part := range parts { for _, part := range parts {
if strings.HasPrefix(part.Mountpoint, "/dev") || (strings.HasPrefix(part.Mountpoint, "/mnt") && !strings.HasPrefix(part.Mountpoint, "/mnt/host")) { if strings.HasPrefix(part.Mountpoint, "/dev") || (strings.HasPrefix(part.Mountpoint, "/mnt") && !strings.HasPrefix(part.Mountpoint, "/mnt/host")) {
// remove /dev/shm and /dev/pts
if part.Mountpoint == "/dev" || strings.HasPrefix(part.Mountpoint, "/dev/shm") || strings.HasPrefix(part.Mountpoint, "/dev/pts") {
continue
}
realMount := part.Mountpoint realMount := part.Mountpoint
if os.Getenv("HOSTNAME") != "" { if os.Getenv("HOSTNAME") != "" {
@ -177,4 +183,31 @@ func GetSystemMetrics() {
} }
} }
} }
// Temperature
temps, err := host.SensorsTemperatures()
avgTemp := 0
avgTempCount := 0
for _, temp := range temps {
utils.Debug("Metrics - Temperature " + temp.SensorKey + " : " + strconv.Itoa(int(temp.Temperature)))
if temp.Temperature > 0 {
avgTemp += int(temp.Temperature)
avgTempCount++
PushSetMetric("system.temp." + temp.SensorKey, int(temp.Temperature), DataDef{
Max: 0,
Period: time.Second * 30,
Label: "Temperature " + temp.SensorKey,
})
}
}
if avgTempCount > 0 {
PushSetMetric("system.temp.all", avgTemp / avgTempCount, DataDef{
Max: 0,
Period: time.Second * 30,
Label: "Temperature",
})
}
} }

View file

@ -6,8 +6,13 @@ import (
"net/url" "net/url"
"strings" "strings"
"crypto/tls" "crypto/tls"
"os"
"io/ioutil"
"strconv"
spa "github.com/roberthodgen/spa-server" spa "github.com/roberthodgen/spa-server"
"github.com/azukaar/cosmos-server/src/utils" "github.com/azukaar/cosmos-server/src/utils"
"github.com/azukaar/cosmos-server/src/docker"
) )
@ -63,6 +68,20 @@ func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, VerboseForwardH
urlQuery := url.RawQuery urlQuery := url.RawQuery
req.URL.Scheme = url.Scheme req.URL.Scheme = url.Scheme
req.URL.Host = url.Host req.URL.Host = url.Host
if route.Mode == "SERVAPP" && os.Getenv("HOSTNAME") == "" {
targetHost := url.Hostname()
targetIP, err := docker.GetContainerIPByName(targetHost)
if err != nil {
utils.Error("Create Route", err)
}
utils.Debug("Dockerless Target IP: " + targetIP)
req.URL.Host = targetIP + ":" + url.Port()
}
utils.Debug("Request to backend: " + req.URL.String())
req.URL.Path, req.URL.RawPath = joinURLPath(url, req.URL) req.URL.Path, req.URL.RawPath = joinURLPath(url, req.URL)
if urlQuery == "" || req.URL.RawQuery == "" { if urlQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = urlQuery + req.URL.RawQuery req.URL.RawQuery = urlQuery + req.URL.RawQuery
@ -105,8 +124,8 @@ func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, VerboseForwardH
} }
// hide hostname (dangerous) // hide hostname (dangerous)
// req.Header.Set("Host", url.Host) // req.Header.Set("Host", req.URL.Host)
// req.Host = url.Host // req.Host = req.URL.Host
req.Header.Set("Host", hostDest) req.Header.Set("Host", hostDest)
req.Host = hostDest req.Host = hostDest
@ -143,6 +162,14 @@ func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, VerboseForwardH
resp.Header.Del("X-XSS-Protection") resp.Header.Del("X-XSS-Protection")
} }
// if 502
if resp.StatusCode == 502 {
// set body
rb := "502 Bad Gateway. This means your container / backend is not reachable by Cosmos."
resp.Body = ioutil.NopCloser(strings.NewReader(rb))
resp.Header.Set("Content-Length", strconv.Itoa(len(rb)))
}
return nil return nil
} }
@ -156,7 +183,7 @@ func RouteTo(route utils.ProxyRouteConfig) http.Handler {
destination := route.Target destination := route.Target
routeType := route.Mode routeType := route.Mode
if(routeType == "SERVAPP" || routeType == "PROXY") { if(routeType == "SERVAPP" || routeType == "PROXY") {
proxy, err := NewProxy(destination, route.AcceptInsecureHTTPSTarget, route.VerboseForwardHeader, route.DisableHeaderHardening, route.CORSOrigin, route) proxy, err := NewProxy(destination, route.AcceptInsecureHTTPSTarget, route.VerboseForwardHeader, route.DisableHeaderHardening, route.CORSOrigin, route)
if err != nil { if err != nil {
utils.Error("Create Route", err) utils.Error("Create Route", err)

View file

@ -37,7 +37,7 @@ var ReBootstrapContainer func(string) error
var LetsEncryptErrors = []string{} var LetsEncryptErrors = []string{}
var CONFIGFOLDER = "/config/" var CONFIGFOLDER = "/var/lib/cosmos/"
var DefaultConfig = Config{ var DefaultConfig = Config{
LoggingLevel: "INFO", LoggingLevel: "INFO",
@ -245,6 +245,7 @@ func GetConfigFileName() string {
configFile := os.Getenv("CONFIG_FILE") configFile := os.Getenv("CONFIG_FILE")
if configFile == "" { if configFile == "" {
CONFIGFOLDER = os.Getenv("COSMOS_CONFIG_FOLDER")
configFile = CONFIGFOLDER + "cosmos.config.json" configFile = CONFIGFOLDER + "cosmos.config.json"
} }