[release] version 0.5.0-unstable7
This commit is contained in:
parent
5545163768
commit
1d10c66a22
|
@ -78,6 +78,8 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
})
|
})
|
||||||
setPortsOptions(portsTemp)
|
setPortsOptions(portsTemp)
|
||||||
|
|
||||||
|
console.log(targetResult)
|
||||||
|
|
||||||
if(targetResult.port == '') {
|
if(targetResult.port == '') {
|
||||||
targetResult.port = '80'
|
targetResult.port = '80'
|
||||||
|
|
||||||
|
@ -117,6 +119,7 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
}
|
}
|
||||||
|
|
||||||
const onContainerChange = (newContainer) => {
|
const onContainerChange = (newContainer) => {
|
||||||
|
console.log(newContainer)
|
||||||
if(loading) return;
|
if(loading) return;
|
||||||
targetResult.container = newContainer.Names[0]
|
targetResult.container = newContainer.Names[0]
|
||||||
targetResult.containerObject = newContainer
|
targetResult.containerObject = newContainer
|
||||||
|
@ -155,7 +158,7 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetResult.container !== 'null') {
|
if (targetResult.container !== 'null') {
|
||||||
postContainerChange(res.data.find((container) => container.Names[0] === targetResult.container))
|
postContainerChange(res.data.find((container) => container.Names[0] === targetResult.container) || targetResult.containerObject)
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -220,7 +223,6 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
)}
|
)}
|
||||||
/>}
|
/>}
|
||||||
{!nameOnly && <>
|
{!nameOnly && <>
|
||||||
{(portsOptions) ? (<>
|
|
||||||
<InputLabel htmlFor={name + "-port"}>Container Port</InputLabel>
|
<InputLabel htmlFor={name + "-port"}>Container Port</InputLabel>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
className="px-2 my-2"
|
className="px-2 my-2"
|
||||||
|
@ -228,8 +230,12 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
name={name + "-port"}
|
name={name + "-port"}
|
||||||
id={name + "-port"}
|
id={name + "-port"}
|
||||||
value={targetResult.port}
|
value={targetResult.port}
|
||||||
options={portsOptions.map((option) => (option))}
|
options={((portsOptions && portsOptions.length) ? portsOptions : [])}
|
||||||
placeholder='Select a port'
|
placeholder='Select a port'
|
||||||
|
onBlur={(event) => {
|
||||||
|
targetResult.port = event.target.value || '';
|
||||||
|
formik.setFieldValue(name, getTarget())
|
||||||
|
}}
|
||||||
freeSolo
|
freeSolo
|
||||||
filterOptions={(x) => x} // disable filtering
|
filterOptions={(x) => x} // disable filtering
|
||||||
getOptionLabel={(option) => '' + option}
|
getOptionLabel={(option) => '' + option}
|
||||||
|
@ -237,7 +243,7 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
return ('' + option) === value
|
return ('' + option) === value
|
||||||
}}
|
}}
|
||||||
onChange={(event, newValue) => {
|
onChange={(event, newValue) => {
|
||||||
targetResult.port = newValue
|
targetResult.port = newValue || '';
|
||||||
formik.setFieldValue(name, getTarget())
|
formik.setFieldValue(name, getTarget())
|
||||||
}}
|
}}
|
||||||
renderInput={(params) => <TextField {...params} />}
|
renderInput={(params) => <TextField {...params} />}
|
||||||
|
@ -245,21 +251,18 @@ export function CosmosContainerPicker({formik, nameOnly, lockTarget, TargetConta
|
||||||
{targetResult.port == '' && targetResult.port == 0 && <FormHelperText error id="standard-weight-helper-text-name-login">
|
{targetResult.port == '' && targetResult.port == 0 && <FormHelperText error id="standard-weight-helper-text-name-login">
|
||||||
Please select a port
|
Please select a port
|
||||||
</FormHelperText>}
|
</FormHelperText>}
|
||||||
</>) : ''}
|
|
||||||
|
|
||||||
|
|
||||||
{(portsOptions) ? (<>
|
<InputLabel htmlFor={name + "-protocol"}>Container Protocol (use HTTP if unsure)</InputLabel>
|
||||||
<InputLabel htmlFor={name + "-protocol"}>Container Protocol (use HTTP if unsure)</InputLabel>
|
<TextField
|
||||||
<TextField
|
type="text"
|
||||||
type="text"
|
name={name + "-protocol"}
|
||||||
name={name + "-protocol"}
|
defaultValue={targetResult.protocol}
|
||||||
defaultValue={targetResult.protocol}
|
onChange={(event) => {
|
||||||
onChange={(event) => {
|
targetResult.protocol = event.target.value && event.target.value.toLowerCase()
|
||||||
targetResult.protocol = event.target.value && event.target.value.toLowerCase()
|
formik.setFieldValue(name, getTarget())
|
||||||
formik.setFieldValue(name, getTarget())
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
</>) : ''}
|
|
||||||
|
|
||||||
<InputLabel htmlFor={name}>Result Target Preview</InputLabel>
|
<InputLabel htmlFor={name}>Result Target Preview</InputLabel>
|
||||||
<TextField
|
<TextField
|
||||||
|
|
|
@ -7,7 +7,8 @@ const GetActions = ({
|
||||||
Id,
|
Id,
|
||||||
state,
|
state,
|
||||||
refreshServeApps,
|
refreshServeApps,
|
||||||
setIsUpdatingId
|
setIsUpdatingId,
|
||||||
|
updateAvailable
|
||||||
}) => {
|
}) => {
|
||||||
const [confirmDelete, setConfirmDelete] = React.useState(false);
|
const [confirmDelete, setConfirmDelete] = React.useState(false);
|
||||||
const isMiniMobile = useMediaQuery((theme) => theme.breakpoints.down('xsm'));
|
const isMiniMobile = useMediaQuery((theme) => theme.breakpoints.down('xsm'));
|
||||||
|
@ -93,7 +94,6 @@ const GetActions = ({
|
||||||
];
|
];
|
||||||
|
|
||||||
return actions.filter((action) => {
|
return actions.filter((action) => {
|
||||||
let updateAvailable = false;
|
|
||||||
return action.if.includes(state) ?? (updateAvailable && action.if.includes('update_available'));
|
return action.if.includes(state) ?? (updateAvailable && action.if.includes('update_available'));
|
||||||
}).map((action) => {
|
}).map((action) => {
|
||||||
return <Tooltip title={action.t}>{action.e}</Tooltip>
|
return <Tooltip title={action.t}>{action.e}</Tooltip>
|
||||||
|
|
|
@ -18,12 +18,20 @@ import NetworkContainerSetup from './network';
|
||||||
import VolumeContainerSetup from './volumes';
|
import VolumeContainerSetup from './volumes';
|
||||||
import DockerTerminal from './terminal';
|
import DockerTerminal from './terminal';
|
||||||
import NewDockerService from './newService';
|
import NewDockerService from './newService';
|
||||||
|
import RouteManagement from '../../config/routes/routeman';
|
||||||
|
|
||||||
|
const getHostnameFromName = (name) => {
|
||||||
|
return name.replace('/', '').replace(/_/g, '-').replace(/[^a-zA-Z0-9-]/g, '').toLowerCase().replace(/\s/g, '-') + '.' + window.location.origin.split('://')[1]
|
||||||
|
}
|
||||||
|
|
||||||
const NewDockerServiceForm = () => {
|
const NewDockerServiceForm = () => {
|
||||||
const [currentTab, setCurrentTab] = React.useState(0);
|
const [currentTab, setCurrentTab] = React.useState(0);
|
||||||
const [maxTab, setMaxTab] = React.useState(0);
|
const [maxTab, setMaxTab] = React.useState(0);
|
||||||
const [containerInfo, setContainerInfo] = React.useState({
|
const [containerInfo, setContainerInfo] = React.useState({
|
||||||
Name: '',
|
Name: '',
|
||||||
|
Names: [],
|
||||||
|
Ports: [], // fake for contianerPicker
|
||||||
|
Route: null,
|
||||||
Config: {
|
Config: {
|
||||||
Env: [],
|
Env: [],
|
||||||
Labels: {},
|
Labels: {},
|
||||||
|
@ -64,6 +72,7 @@ const NewDockerServiceForm = () => {
|
||||||
acc[cur] = {};
|
acc[cur] = {};
|
||||||
return acc;
|
return acc;
|
||||||
}, {}),
|
}, {}),
|
||||||
|
Routes: [containerInfo.Route]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -90,7 +99,7 @@ const NewDockerServiceForm = () => {
|
||||||
variant="contained"
|
variant="contained"
|
||||||
fullWidth
|
fullWidth
|
||||||
endIcon={<ArrowRightOutlined />}
|
endIcon={<ArrowRightOutlined />}
|
||||||
disabled={currentTab === 3}
|
disabled={currentTab === 4}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentTab(currentTab + 1);
|
setCurrentTab(currentTab + 1);
|
||||||
setMaxTab(Math.max(currentTab + 1, maxTab));
|
setMaxTab(Math.max(currentTab + 1, maxTab));
|
||||||
|
@ -100,6 +109,8 @@ const NewDockerServiceForm = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
|
console.log(containerInfo)
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<Stack spacing={1}>
|
<Stack spacing={1}>
|
||||||
<Stack direction="row" spacing={1} alignItems="center">
|
<Stack direction="row" spacing={1} alignItems="center">
|
||||||
|
@ -119,6 +130,7 @@ const NewDockerServiceForm = () => {
|
||||||
const newValues = {
|
const newValues = {
|
||||||
...containerInfo,
|
...containerInfo,
|
||||||
Name: values.name,
|
Name: values.name,
|
||||||
|
Names: [values.name],
|
||||||
Config: {
|
Config: {
|
||||||
...containerInfo.Config,
|
...containerInfo.Config,
|
||||||
Image: values.image,
|
Image: values.image,
|
||||||
|
@ -149,6 +161,44 @@ const NewDockerServiceForm = () => {
|
||||||
setContainerInfo(newValues);
|
setContainerInfo(newValues);
|
||||||
}}/>{nav()}</Stack>
|
}}/>{nav()}</Stack>
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'URL',
|
||||||
|
disabled: maxTab < 1,
|
||||||
|
children: <Stack spacing={2}><RouteManagement TargetContainer={containerInfo}
|
||||||
|
routeConfig={{
|
||||||
|
Target: "http://"+containerInfo.Name.replace('/', '') + ":",
|
||||||
|
Mode: "SERVAPP",
|
||||||
|
Name: containerInfo.Name.replace('/', ''),
|
||||||
|
Description: "Expose " + containerInfo.Name.replace('/', '') + " to the internet",
|
||||||
|
UseHost: true,
|
||||||
|
Host: getHostnameFromName(containerInfo.Name),
|
||||||
|
UsePathPrefix: false,
|
||||||
|
PathPrefix: '',
|
||||||
|
CORSOrigin: '',
|
||||||
|
StripPathPrefix: false,
|
||||||
|
AuthEnabled: false,
|
||||||
|
Timeout: 14400000,
|
||||||
|
ThrottlePerMinute: 10000,
|
||||||
|
BlockCommonBots: true,
|
||||||
|
SmartShield: {
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
routeNames={[]}
|
||||||
|
setRouteConfig={(newRoute) => {
|
||||||
|
const newValues = {
|
||||||
|
...containerInfo,
|
||||||
|
Route: newRoute,
|
||||||
|
}
|
||||||
|
setContainerInfo(newValues);
|
||||||
|
}}
|
||||||
|
up={() => {}}
|
||||||
|
down={() => {}}
|
||||||
|
deleteRoute={() => {}}
|
||||||
|
noControls
|
||||||
|
lockTarget
|
||||||
|
/>{nav()}</Stack>
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Network',
|
title: 'Network',
|
||||||
disabled: maxTab < 1,
|
disabled: maxTab < 1,
|
||||||
|
@ -204,7 +254,7 @@ const NewDockerServiceForm = () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Storage',
|
title: 'Storage',
|
||||||
disabled: maxTab < 2,
|
disabled: maxTab < 1,
|
||||||
children: <Stack spacing={2}><VolumeContainerSetup newContainer containerInfo={containerInfo} OnChange={(values) => {
|
children: <Stack spacing={2}><VolumeContainerSetup newContainer containerInfo={containerInfo} OnChange={(values) => {
|
||||||
console.log(values)
|
console.log(values)
|
||||||
const newValues = {
|
const newValues = {
|
||||||
|
@ -225,7 +275,7 @@ const NewDockerServiceForm = () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Review & Start',
|
title: 'Review & Start',
|
||||||
disabled: maxTab < 3,
|
disabled: maxTab < 1,
|
||||||
children: <Stack spacing={2}><NewDockerService service={service} />{nav()}</Stack>
|
children: <Stack spacing={2}><NewDockerService service={service} />{nav()}</Stack>
|
||||||
}
|
}
|
||||||
]} />}
|
]} />}
|
||||||
|
|
|
@ -39,6 +39,7 @@ const ServeApps = () => {
|
||||||
const [isUpdating, setIsUpdating] = useState({});
|
const [isUpdating, setIsUpdating] = useState({});
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const [config, setConfig] = useState(null);
|
const [config, setConfig] = useState(null);
|
||||||
|
const [updatesAvailable, setUpdatesAvailable] = useState(null);
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const [newRoute, setNewRoute] = useState(null);
|
const [newRoute, setNewRoute] = useState(null);
|
||||||
const [submitErrors, setSubmitErrors] = useState([]);
|
const [submitErrors, setSubmitErrors] = useState([]);
|
||||||
|
@ -50,6 +51,7 @@ const ServeApps = () => {
|
||||||
});
|
});
|
||||||
API.config.get().then((res) => {
|
API.config.get().then((res) => {
|
||||||
setConfig(res.data);
|
setConfig(res.data);
|
||||||
|
setUpdatesAvailable(res.updates);
|
||||||
});
|
});
|
||||||
setIsUpdating({});
|
setIsUpdating({});
|
||||||
};
|
};
|
||||||
|
@ -190,7 +192,13 @@ const ServeApps = () => {
|
||||||
{/* <Button variant="contained" size="small" onClick={() => {}}>
|
{/* <Button variant="contained" size="small" onClick={() => {}}>
|
||||||
Update
|
Update
|
||||||
</Button> */}
|
</Button> */}
|
||||||
<GetActions Id={app.Names[0].replace('/', '')} state={app.State} setIsUpdatingId={setIsUpdatingId} refreshServeApps={refreshServeApps} />
|
<GetActions
|
||||||
|
Id={app.Names[0].replace('/', '')}
|
||||||
|
state={app.State}
|
||||||
|
setIsUpdatingId={setIsUpdatingId}
|
||||||
|
refreshServeApps={refreshServeApps}
|
||||||
|
updateAvailable={updatesAvailable[app.Names[0]]}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
|
<Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cosmos-server",
|
"name": "cosmos-server",
|
||||||
"version": "0.5.0-unstable6",
|
"version": "0.5.0-unstable7",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "test-server.js",
|
"main": "test-server.js",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/azukaar/cosmos-server/src/utils"
|
"github.com/azukaar/cosmos-server/src/utils"
|
||||||
|
"github.com/azukaar/cosmos-server/src/docker"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -96,9 +97,17 @@ func checkVersion() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkUpdatesAvailable() {
|
||||||
|
utils.UpdateAvailable = docker.CheckUpdatesAvailable()
|
||||||
|
}
|
||||||
|
|
||||||
func CRON() {
|
func CRON() {
|
||||||
go func() {
|
go func() {
|
||||||
gocron.Every(1).Day().At("00:00").Do(checkVersion)
|
gocron.Every(1).Day().At("00:00").Do(checkVersion)
|
||||||
<-gocron.Start()
|
<-gocron.Start()
|
||||||
}()
|
}()
|
||||||
|
go func() {
|
||||||
|
gocron.Every(6).Hours().Do(checkUpdatesAvailable)
|
||||||
|
<-gocron.Start()
|
||||||
|
}()
|
||||||
}
|
}
|
|
@ -39,6 +39,7 @@ func ConfigApiGet(w http.ResponseWriter, req *http.Request) {
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
"status": "OK",
|
"status": "OK",
|
||||||
"data": config,
|
"data": config,
|
||||||
|
"updates": utils.UpdateAvailable,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
utils.Error("SettingGet: Method not allowed" + req.Method, nil)
|
utils.Error("SettingGet: Method not allowed" + req.Method, nil)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"fmt"
|
"fmt"
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"strings"
|
||||||
"github.com/azukaar/cosmos-server/src/utils"
|
"github.com/azukaar/cosmos-server/src/utils"
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
@ -312,3 +313,46 @@ func Test() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func CheckUpdatesAvailable() map[string]bool {
|
||||||
|
result := make(map[string]bool)
|
||||||
|
|
||||||
|
// for each containers
|
||||||
|
containers, err := ListContainers()
|
||||||
|
if err != nil {
|
||||||
|
utils.Error("CheckUpdatesAvailable", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, container := range containers {
|
||||||
|
utils.Log("Checking for updates for " + container.Image)
|
||||||
|
|
||||||
|
rc, err := DockerClient.ImagePull(DockerContext, container.Image, types.ImagePullOptions{})
|
||||||
|
if err != nil {
|
||||||
|
utils.Error("CheckUpdatesAvailable", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(rc)
|
||||||
|
defer rc.Close()
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
newStr := scanner.Text()
|
||||||
|
|
||||||
|
// Check if a download has started
|
||||||
|
if strings.Contains(newStr, "\"status\":\"Pulling fs layer\"") {
|
||||||
|
utils.Log("Updates available for " + container.Image)
|
||||||
|
result[container.Names[0]] = true
|
||||||
|
rc.Close()
|
||||||
|
break
|
||||||
|
} else if strings.Contains(newStr, "\"status\":\"Status: Image is up to date\"") {
|
||||||
|
utils.Log("No updates available for " + container.Image)
|
||||||
|
rc.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ var NewVersionAvailable = false
|
||||||
|
|
||||||
var NeedsRestart = false
|
var NeedsRestart = false
|
||||||
|
|
||||||
|
var UpdateAvailable = map[string]bool{}
|
||||||
|
|
||||||
var DefaultConfig = Config{
|
var DefaultConfig = Config{
|
||||||
LoggingLevel: "INFO",
|
LoggingLevel: "INFO",
|
||||||
NewInstall: true,
|
NewInstall: true,
|
||||||
|
|
Loading…
Reference in a new issue