[release] version 0.5.5

This commit is contained in:
Yann Stepienik 2023-05-19 16:23:05 +01:00
parent c8731e2fa7
commit a6098f0507
23 changed files with 654 additions and 484 deletions

View file

@ -42,14 +42,63 @@ let isOnline = () => {
});
}
let newInstall = (req) => {
return wrap(fetch('/cosmos/api/newInstall', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(req)
}))
let newInstall = (req, onProgress) => {
if(req.step == '2') {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(req)
};
return fetch('/cosmos/api/newInstall', requestOptions)
.then(response => {
if (!response.ok) {
throw new Error(response.statusText);
}
// The response body is a ReadableStream. This code reads the stream and passes chunks to the callback.
const reader = response.body.getReader();
// Read the stream and pass chunks to the callback as they arrive
return new ReadableStream({
start(controller) {
function read() {
return reader.read().then(({ done, value }) => {
if (done) {
controller.close();
return;
}
// Decode the UTF-8 text
let text = new TextDecoder().decode(value);
// Split by lines in case there are multiple lines in one chunk
let lines = text.split('\n');
for (let line of lines) {
if (line) {
// Call the progress callback
onProgress(line);
}
}
controller.enqueue(value);
return read();
});
}
return read();
}
});
}).catch((e) => {
alert(e);
});
} else {
return wrap(fetch('/cosmos/api/newInstall', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(req)
}))
}
}
const isDemo = import.meta.env.MODE === 'demo';

View file

@ -0,0 +1,9 @@
import { WarningFilled } from "@ant-design/icons";
import { Tooltip } from "@mui/material";
export const ContainerNetworkWarning = ({container}) => (
container.HostConfig.NetworkMode != "bridge" && container.HostConfig.NetworkMode != "default" &&
<Tooltip title={`This container is using an incompatible network mode (${container.HostConfig.NetworkMode.slice(0, 16)}). If you want Cosmos to proxy to this container, enabling this option will change the network mode to bridge for you. Otherwise, you dont need to do anything, as the container is already isolated. Note that changing to bridge might break connectivity to other containers. To fix it, please use a private network and static ips instead.`}>
<WarningFilled style={{color: 'red', fontSize: '18px', paddingLeft: '10px', paddingRight: '10px'}} />
</Tooltip>
);

View file

@ -14,6 +14,7 @@ import { useEffect, useState } from 'react';
import * as API from '../../api';
import { Formik } from 'formik';
import LogsInModal from '../../components/logsInModal';
import { CosmosCheckbox, CosmosInputPassword, CosmosInputText, CosmosSelect } from '../config/users/formShortcuts';
import AnimateButton from '../../components/@extended/AnimateButton';
import { Box } from '@mui/system';
@ -25,6 +26,7 @@ const NewInstall = () => {
const [counter, setCounter] = useState(0);
let [hostname, setHostname] = useState('');
const [databaseEnable, setDatabaseEnable] = useState(true);
const [pullRequest, setPullRequest] = useState(null);
const refreshStatus = async () => {
try {
@ -118,27 +120,29 @@ const NewInstall = () => {
validate={(values) => {
}}
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
try {
setSubmitting(true);
const res = await API.newInstall({
setSubmitting(true);
setPullRequest(() => ((cb) => {
API.newInstall({
step: "2",
MongoDBMode: values.DBMode,
MongoDB: values.MongoDB,
});
if(res.status == "OK") {
if(values.DBMode === "DisableUserManagement") {
setDatabaseEnable(false);
}
setStatus({ success: true });
}
} catch (error) {
setStatus({ success: false });
setErrors({ submit: error.message });
setSubmitting(false);
}
}, cb)
}));
}}>
{(formik) => (
<form noValidate onSubmit={formik.handleSubmit}>
<LogsInModal
request={pullRequest}
title="Installing Database..."
OnSuccess={() => {
if(formik.values.DBMode === "DisableUserManagement") {
setDatabaseEnable(false);
}
formik.setStatus({ success: true });
formik.setSubmitting(false);
}}
/>
<Stack item xs={12} spacing={2}>
<CosmosSelect
name="DBMode"

View file

@ -16,8 +16,7 @@ const GetActions = ({
const isMiniMobile = useMediaQuery((theme) => theme.breakpoints.down('xsm'));
const [pullRequest, setPullRequest] = React.useState(null);
const [isUpdating, setIsUpdating] = React.useState(false);
console.log(isMiniMobile)
const doTo = (action) => {
setIsUpdating(true);

View file

@ -116,6 +116,30 @@ const DockerComposeImport = ({refresh}) => {
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('=');
labels[''+key] = ''+value;
});
doc.services[key].labels = labels;
}
}
// convert network
if(doc.services[key].networks) {
if(Array.isArray(doc.services[key].networks)) {
let networks = {};
doc.services[key].networks.forEach((network) => {
networks[''+network] = {};
});
doc.services[key].networks = networks;
}
}
});
}

View file

@ -67,6 +67,7 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh, newContainer, O
<div style={{ maxWidth: '1000px', width: '100%', margin: '', position: 'relative' }}>
<Formik
initialValues={{
networkMode: containerInfo.HostConfig.NetworkMode,
ports: Object.keys(containerInfo.NetworkSettings.Ports).map((port) => {
return {
port: port.split('/')[0],
@ -237,6 +238,14 @@ const NetworkContainerSetup = ({ config, containerInfo, refresh, newContainer, O
</MainCard>
<MainCard title={'Networks'}>
<Stack spacing={2}>
<CosmosInputText
label="Network Mode"
name="networkMode"
placeholder={'default'}
formik={formik}
/>
{networks && <Stack spacing={2}>
{Object.keys(containerInfo.NetworkSettings.Networks).map((networkName) => {
const network = networks.find((n) => n.Name === networkName);

View file

@ -99,7 +99,7 @@ const NewDockerServiceForm = () => {
variant="contained"
fullWidth
endIcon={<ArrowRightOutlined />}
disabled={currentTab === 4}
disabled={(currentTab === 4) || containerInfo.Name === '' || containerInfo.Config.Image === ''}
onClick={() => {
setCurrentTab(currentTab + 1);
setMaxTab(Math.max(currentTab + 1, maxTab));

View file

@ -108,8 +108,8 @@ const ContainerOverview = ({ containerInfo, config, refresh }) => {
)}
<strong><ContainerOutlined /> Image</strong>
<div style={info}>{Image}</div>
<strong><DesktopOutlined /> Name</strong>
<div style={info}>{Name}</div>
<strong><DesktopOutlined /> ID</strong>
<div style={info}>{containerInfo.Id}</div>
<strong><InfoCircleOutlined /> IP Address</strong>
<div style={info}>{IPAddress}</div>
<strong>

View file

@ -61,6 +61,9 @@ const DockerContainerSetup = ({config, containerInfo, OnChange, refresh, newCont
if (!values.image) {
errors.image = 'Required';
}
if (!values.name && newContainer) {
errors.name = 'Required';
}
// env keys and labels key mustbe unique
const envKeys = values.envVars.map((envVar) => envVar.key);
const labelKeys = values.labels.map((label) => label.key);

View file

@ -1,5 +1,5 @@
// material-ui
import { AppstoreAddOutlined, CloseSquareOutlined, DeleteOutlined, PauseCircleOutlined, PlaySquareOutlined, PlusCircleOutlined, ReloadOutlined, RollbackOutlined, SearchOutlined, SettingOutlined, StopOutlined, UpCircleOutlined, UpSquareFilled } from '@ant-design/icons';
import { AlertFilled, AppstoreAddOutlined, CloseSquareOutlined, DeleteOutlined, PauseCircleOutlined, PlaySquareOutlined, PlusCircleOutlined, ReloadOutlined, RollbackOutlined, SearchOutlined, SettingOutlined, StopOutlined, UpCircleOutlined, UpSquareFilled, WarningFilled } from '@ant-design/icons';
import { Alert, Badge, Button, Card, Checkbox, Chip, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, IconButton, Input, InputAdornment, TextField, Tooltip, Typography } from '@mui/material';
import Grid2 from '@mui/material/Unstable_Grid2/Grid2';
import { Stack } from '@mui/system';
@ -18,6 +18,7 @@ import ExposeModal from './exposeModal';
import GetActions from './actionBar';
import ResponsiveButton from '../../components/responseiveButton';
import DockerComposeImport from './containers/docker-compose';
import { ContainerNetworkWarning } from '../../components/containers';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
@ -185,7 +186,7 @@ const ServeApps = () => {
<img className="loading-image" alt="" src={getFirstRouteFavIcon(app)} width="40px" />
<Stack direction="column" spacing={0} alignItems="flex-start" style={{height: '40px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'no-wrap'}}>
<Typography variant="h5" color="text.secondary">
{app.Names[0].replace('/', '')}&nbsp;
{app.Names[0].replace('/', '')}&nbsp;
</Typography>
<Typography color="text.secondary" style={{fontSize: '80%', whiteSpace: 'nowrap', overflow: 'hidden', maxWidth: '100%', textOverflow: 'ellipsis'}}>
{app.Image}
@ -251,7 +252,7 @@ const ServeApps = () => {
refreshServeApps();
})
}}
/> Force Secure Network
/> Force Secure Network <ContainerNetworkWarning container={app} />
</Stack>
<Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
<Checkbox

View file

@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.5.4",
"version": "0.5.5",
"description": "",
"main": "test-server.js",
"bugs": {

View file

@ -39,7 +39,7 @@ func AutoUpdateContainerRoute(w http.ResponseWriter, req *http.Request) {
utils.Log("API: Set Auto Update "+status+" : " + containerName)
_, errEdit := EditContainer(container.ID, container)
_, errEdit := EditContainer(container.ID, container, false)
if errEdit != nil {
utils.Error("AutoUpdateContainer Edit", errEdit)
utils.HTTPError(w, "Internal server error: " + errEdit.Error(), http.StatusInternalServerError, "DS003")

View file

@ -167,377 +167,27 @@ func CreateServiceRoute(w http.ResponseWriter, req *http.Request) {
}
if req.Method == "POST" {
// Enable streaming of response by setting appropriate headers
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Transfer-Encoding", "chunked")
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}
utils.ConfigLock.Lock()
defer utils.ConfigLock.Unlock()
utils.Log("Starting creation of new service...")
fmt.Fprintf(w, "Starting creation of new service...\n")
flusher.Flush()
config := utils.ReadConfigFromFile()
configRoutes := config.HTTPConfig.ProxyConfig.Routes
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}
decoder := json.NewDecoder(req.Body)
var serviceRequest DockerServiceCreateRequest
err := decoder.Decode(&serviceRequest)
if err != nil {
utils.Error("CreateService - decode - ", err)
utils.HTTPError(w, "Bad request: "+err.Error(), http.StatusBadRequest, "DS003")
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
}
var rollbackActions []DockerServiceCreateRollback
// Create networks
for networkToCreateName, networkToCreate := range serviceRequest.Networks {
utils.Log(fmt.Sprintf("Creating network %s...", networkToCreateName))
fmt.Fprintf(w, "Creating network %s...\n", networkToCreateName)
flusher.Flush()
// check if network already exists
_, err = DockerClient.NetworkInspect(DockerContext, networkToCreateName, doctype.NetworkInspectOptions{})
if err == nil {
utils.Error("CreateService: Network", err)
fmt.Fprintf(w, "[ERROR] Network %s already exists\n", networkToCreateName)
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
ipamConfig := make([]network.IPAMConfig, len(networkToCreate.IPAM.Config))
if networkToCreate.IPAM.Config != nil {
for i, config := range networkToCreate.IPAM.Config {
ipamConfig[i] = network.IPAMConfig{
Subnet: config.Subnet,
}
}
}
_, err = DockerClient.NetworkCreate(DockerContext, networkToCreateName, doctype.NetworkCreate{
Driver: networkToCreate.Driver,
Attachable: networkToCreate.Attachable,
Internal: networkToCreate.Internal,
EnableIPv6: networkToCreate.EnableIPv6,
IPAM: &network.IPAM{
Driver: networkToCreate.IPAM.Driver,
Config: ipamConfig,
},
})
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Network", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Network creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
Action: "remove",
Type: "network",
Name: networkToCreateName,
})
// Write a response to the client
utils.Log(fmt.Sprintf("Network %s created", networkToCreateName))
fmt.Fprintf(w, "Network %s created\n", networkToCreateName)
flusher.Flush()
}
// Create volumes
for _, volume := range serviceRequest.Volumes {
utils.Log(fmt.Sprintf("Creating volume %s...", volume.Name))
fmt.Fprintf(w, "Creating volume %s...\n", volume.Name)
flusher.Flush()
_, err = DockerClient.VolumeCreate(DockerContext, volumetype.CreateOptions{
Driver: volume.Driver,
Name: volume.Name,
})
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Volume", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Volume creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
Action: "remove",
Type: "volume",
Name: volume.Name,
})
// Write a response to the client
utils.Log(fmt.Sprintf("Volume %s created", volume.Name))
fmt.Fprintf(w, "Volume %s created\n", volume.Name)
flusher.Flush()
}
// pull images
for _, container := range serviceRequest.Services {
// Write a response to the client
utils.Log(fmt.Sprintf("Pulling image %s", container.Image))
fmt.Fprintf(w, "Pulling image %s\n", container.Image)
flusher.Flush()
out, err := DockerClient.ImagePull(DockerContext, container.Image, doctype.ImagePullOptions{})
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Image pull", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Image pull error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
defer out.Close()
// wait for image pull to finish
scanner := bufio.NewScanner(out)
for scanner.Scan() {
fmt.Fprintf(w, "%s\n", scanner.Text())
flusher.Flush()
}
// Write a response to the client
utils.Log(fmt.Sprintf("Image %s pulled", container.Image))
fmt.Fprintf(w, "Image %s pulled\n", container.Image)
flusher.Flush()
}
// Create containers
for _, container := range serviceRequest.Services {
utils.Log(fmt.Sprintf("Creating container %s...", container.Name))
fmt.Fprintf(w, "Creating container %s...\n", container.Name)
flusher.Flush()
containerConfig := &conttype.Config{
Image: container.Image,
Env: container.Environment,
Labels: container.Labels,
ExposedPorts: nat.PortSet{},
WorkingDir: container.WorkingDir,
User: container.User,
Hostname: container.Hostname,
Domainname: container.Domainname,
MacAddress: container.MacAddress,
StopSignal: container.StopSignal,
StopTimeout: &container.StopGracePeriod,
Tty: container.Tty,
OpenStdin: container.StdinOpen,
}
if container.Command != "" {
containerConfig.Cmd = strings.Fields(container.Command)
}
if container.Entrypoint != "" {
containerConfig.Entrypoint = strslice.StrSlice(strings.Fields(container.Entrypoint))
}
// For Expose / Ports
for _, expose := range container.Expose {
exposePort := nat.Port(expose)
containerConfig.ExposedPorts[exposePort] = struct{}{}
}
PortBindings := nat.PortMap{}
for _, port := range container.Ports {
portContainer := strings.Split(port, ":")[0]
portHost := strings.Split(port, ":")[1]
containerConfig.ExposedPorts[nat.Port(portContainer)] = struct{}{}
PortBindings[nat.Port(portContainer)] = []nat.PortBinding{
{
HostIP: "",
HostPort: portHost,
},
}
}
// Create missing folders for bind mounts
for _, newmount := range container.Volumes {
if newmount.Type == mount.TypeBind {
if _, err := os.Stat(newmount.Source); os.IsNotExist(err) {
err := os.MkdirAll(newmount.Source, 0755)
if err != nil {
utils.Error("CreateService: Unable to create directory for bind mount", err)
fmt.Fprintf(w, "[ERROR] Unable to create directory for bind mount: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
if container.User != "" {
// Change the ownership of the directory to the container.User
userInfo, err := user.Lookup(container.User)
if err != nil {
utils.Error("CreateService: Unable to lookup user", err)
fmt.Fprintf(w, "[ERROR] Unable to lookup user " + container.User + "." +err.Error())
flusher.Flush()
} else {
uid, _ := strconv.Atoi(userInfo.Uid)
gid, _ := strconv.Atoi(userInfo.Gid)
err = os.Chown(newmount.Source, uid, gid)
if err != nil {
utils.Error("CreateService: Unable to change ownership of directory", err)
fmt.Fprintf(w, "[ERROR] Unable to change ownership of directory: "+err.Error())
flusher.Flush()
}
}
}
}
}
}
hostConfig := &conttype.HostConfig{
PortBindings: PortBindings,
Mounts: container.Volumes,
RestartPolicy: conttype.RestartPolicy{
Name: container.RestartPolicy,
},
Privileged: container.Privileged,
NetworkMode: conttype.NetworkMode(container.NetworkMode),
DNS: container.DNS,
DNSSearch: container.DNSSearch,
ExtraHosts: container.ExtraHosts,
Links: container.Links,
SecurityOpt: container.SecurityOpt,
StorageOpt: container.StorageOpt,
Sysctls: container.Sysctls,
Isolation: conttype.Isolation(container.Isolation),
CapAdd: container.CapAdd,
CapDrop: container.CapDrop,
}
// For Healthcheck
if len(container.HealthCheck.Test) > 0 {
containerConfig.Healthcheck = &conttype.HealthConfig{
Test: container.HealthCheck.Test,
Interval: time.Duration(container.HealthCheck.Interval) * time.Second,
Timeout: time.Duration(container.HealthCheck.Timeout) * time.Second,
StartPeriod: time.Duration(container.HealthCheck.StartPeriod) * time.Second,
Retries: container.HealthCheck.Retries,
}
}
// For Devices
devices := []conttype.DeviceMapping{}
for _, device := range container.Devices {
deviceSplit := strings.Split(device, ":")
devices = append(devices, conttype.DeviceMapping{
PathOnHost: deviceSplit[0],
PathInContainer: deviceSplit[1],
CgroupPermissions: "rwm", // This can be "r", "w", "m", or any combination
})
}
hostConfig.Devices = devices
networkingConfig := &network.NetworkingConfig{
EndpointsConfig: make(map[string]*network.EndpointSettings),
}
for netName, netConfig := range container.Networks {
networkingConfig.EndpointsConfig[netName] = &network.EndpointSettings{
Aliases: netConfig.Aliases,
IPAddress: netConfig.IPV4Address,
GlobalIPv6Address: netConfig.IPV6Address,
}
}
_, err = DockerClient.ContainerCreate(DockerContext, containerConfig, hostConfig, networkingConfig, nil, container.Name)
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Container", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Container creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
Action: "remove",
Type: "container",
Name: container.Name,
})
// add routes
for _, route := range container.Routes {
// check if route already exists
exists := false
for _, configRoute := range configRoutes {
if configRoute.Name == route.Name {
exists = true
break
}
}
if !exists {
configRoutes = append([]utils.ProxyRouteConfig{(utils.ProxyRouteConfig)(route)}, configRoutes...)
} else {
utils.Error("CreateService: Rolling back changes because of -- Route already exist", nil)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Route already exist")
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
}
// Write a response to the client
utils.Log(fmt.Sprintf("Container %s created", container.Name))
fmt.Fprintf(w, "Container %s created\n", container.Name)
flusher.Flush()
}
// re-order containers dpeneding on depends_on
startOrder, err := ReOrderServices(serviceRequest.Services)
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Container", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Container creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
// Start all the newly created containers
for _, container := range startOrder {
err = DockerClient.ContainerStart(DockerContext, container.Name, doctype.ContainerStartOptions{})
if err != nil {
utils.Error("CreateService: Start Container", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Container start error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return
}
// Write a response to the client
utils.Log(fmt.Sprintf("Container %s started", container.Name))
fmt.Fprintf(w, "Container %s started\n", container.Name)
flusher.Flush()
}
// Save the route configs
config.HTTPConfig.ProxyConfig.Routes = configRoutes
utils.SaveConfigTofile(config)
utils.NeedsRestart = true
// After all operations
utils.Log("CreateService: Operation succeeded. SERVICE STARTED")
fmt.Fprintf(w, "[OPERATION SUCCEEDED]. SERVICE STARTED\n")
flusher.Flush()
CreateService(w, req, serviceRequest)
} else {
utils.Error("CreateService: Method not allowed" + req.Method, nil)
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
@ -545,6 +195,375 @@ func CreateServiceRoute(w http.ResponseWriter, req *http.Request) {
}
}
func CreateService(w http.ResponseWriter, req *http.Request, serviceRequest DockerServiceCreateRequest) error {
// Enable streaming of response by setting appropriate headers
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Transfer-Encoding", "chunked")
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return errors.New("Streaming unsupported!")
}
utils.ConfigLock.Lock()
defer utils.ConfigLock.Unlock()
utils.Log("Starting creation of new service...")
fmt.Fprintf(w, "Starting creation of new service...\n")
flusher.Flush()
config := utils.ReadConfigFromFile()
configRoutes := config.HTTPConfig.ProxyConfig.Routes
var rollbackActions []DockerServiceCreateRollback
var err error
// Create networks
for networkToCreateName, networkToCreate := range serviceRequest.Networks {
utils.Log(fmt.Sprintf("Creating network %s...", networkToCreateName))
fmt.Fprintf(w, "Creating network %s...\n", networkToCreateName)
flusher.Flush()
// check if network already exists
_, err = DockerClient.NetworkInspect(DockerContext, networkToCreateName, doctype.NetworkInspectOptions{})
if err == nil {
utils.Error("CreateService: Network", err)
fmt.Fprintf(w, "[ERROR] Network %s already exists\n", networkToCreateName)
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
ipamConfig := make([]network.IPAMConfig, len(networkToCreate.IPAM.Config))
if networkToCreate.IPAM.Config != nil {
for i, config := range networkToCreate.IPAM.Config {
ipamConfig[i] = network.IPAMConfig{
Subnet: config.Subnet,
}
}
}
_, err = DockerClient.NetworkCreate(DockerContext, networkToCreateName, doctype.NetworkCreate{
Driver: networkToCreate.Driver,
Attachable: networkToCreate.Attachable,
Internal: networkToCreate.Internal,
EnableIPv6: networkToCreate.EnableIPv6,
IPAM: &network.IPAM{
Driver: networkToCreate.IPAM.Driver,
Config: ipamConfig,
},
})
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Network", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Network creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
Action: "remove",
Type: "network",
Name: networkToCreateName,
})
// Write a response to the client
utils.Log(fmt.Sprintf("Network %s created", networkToCreateName))
fmt.Fprintf(w, "Network %s created\n", networkToCreateName)
flusher.Flush()
}
// Create volumes
for _, volume := range serviceRequest.Volumes {
utils.Log(fmt.Sprintf("Creating volume %s...", volume.Name))
fmt.Fprintf(w, "Creating volume %s...\n", volume.Name)
flusher.Flush()
_, err = DockerClient.VolumeCreate(DockerContext, volumetype.CreateOptions{
Driver: volume.Driver,
Name: volume.Name,
})
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Volume", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Volume creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
Action: "remove",
Type: "volume",
Name: volume.Name,
})
// Write a response to the client
utils.Log(fmt.Sprintf("Volume %s created", volume.Name))
fmt.Fprintf(w, "Volume %s created\n", volume.Name)
flusher.Flush()
}
// pull images
for _, container := range serviceRequest.Services {
// Write a response to the client
utils.Log(fmt.Sprintf("Pulling image %s", container.Image))
fmt.Fprintf(w, "Pulling image %s\n", container.Image)
flusher.Flush()
out, err := DockerClient.ImagePull(DockerContext, container.Image, doctype.ImagePullOptions{})
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Image pull", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Image pull error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
defer out.Close()
// wait for image pull to finish
scanner := bufio.NewScanner(out)
for scanner.Scan() {
fmt.Fprintf(w, "%s\n", scanner.Text())
flusher.Flush()
}
// Write a response to the client
utils.Log(fmt.Sprintf("Image %s pulled", container.Image))
fmt.Fprintf(w, "Image %s pulled\n", container.Image)
flusher.Flush()
}
// Create containers
for _, container := range serviceRequest.Services {
utils.Log(fmt.Sprintf("Creating container %s...", container.Name))
fmt.Fprintf(w, "Creating container %s...\n", container.Name)
flusher.Flush()
containerConfig := &conttype.Config{
Image: container.Image,
Env: container.Environment,
Labels: container.Labels,
ExposedPorts: nat.PortSet{},
WorkingDir: container.WorkingDir,
User: container.User,
Hostname: container.Hostname,
Domainname: container.Domainname,
MacAddress: container.MacAddress,
StopSignal: container.StopSignal,
StopTimeout: &container.StopGracePeriod,
Tty: container.Tty,
OpenStdin: container.StdinOpen,
}
if container.Command != "" {
containerConfig.Cmd = strings.Fields(container.Command)
}
if container.Entrypoint != "" {
containerConfig.Entrypoint = strslice.StrSlice(strings.Fields(container.Entrypoint))
}
// For Expose / Ports
for _, expose := range container.Expose {
exposePort := nat.Port(expose)
containerConfig.ExposedPorts[exposePort] = struct{}{}
}
PortBindings := nat.PortMap{}
for _, port := range container.Ports {
portContainer := strings.Split(port, ":")[0]
portHost := strings.Split(port, ":")[1]
containerConfig.ExposedPorts[nat.Port(portContainer)] = struct{}{}
PortBindings[nat.Port(portContainer)] = []nat.PortBinding{
{
HostIP: "",
HostPort: portHost,
},
}
}
// Create missing folders for bind mounts
for _, newmount := range container.Volumes {
if newmount.Type == mount.TypeBind {
if _, err := os.Stat(newmount.Source); os.IsNotExist(err) {
err := os.MkdirAll(newmount.Source, 0755)
if err != nil {
utils.Error("CreateService: Unable to create directory for bind mount", err)
fmt.Fprintf(w, "[ERROR] Unable to create directory for bind mount: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
if container.User != "" {
// Change the ownership of the directory to the container.User
userInfo, err := user.Lookup(container.User)
if err != nil {
utils.Error("CreateService: Unable to lookup user", err)
fmt.Fprintf(w, "[ERROR] Unable to lookup user " + container.User + "." +err.Error())
flusher.Flush()
} else {
uid, _ := strconv.Atoi(userInfo.Uid)
gid, _ := strconv.Atoi(userInfo.Gid)
err = os.Chown(newmount.Source, uid, gid)
if err != nil {
utils.Error("CreateService: Unable to change ownership of directory", err)
fmt.Fprintf(w, "[ERROR] Unable to change ownership of directory: "+err.Error())
flusher.Flush()
}
}
}
}
}
}
hostConfig := &conttype.HostConfig{
PortBindings: PortBindings,
Mounts: container.Volumes,
RestartPolicy: conttype.RestartPolicy{
Name: container.RestartPolicy,
},
Privileged: container.Privileged,
NetworkMode: conttype.NetworkMode(container.NetworkMode),
DNS: container.DNS,
DNSSearch: container.DNSSearch,
ExtraHosts: container.ExtraHosts,
Links: container.Links,
SecurityOpt: container.SecurityOpt,
StorageOpt: container.StorageOpt,
Sysctls: container.Sysctls,
Isolation: conttype.Isolation(container.Isolation),
CapAdd: container.CapAdd,
CapDrop: container.CapDrop,
}
// For Healthcheck
if len(container.HealthCheck.Test) > 0 {
containerConfig.Healthcheck = &conttype.HealthConfig{
Test: container.HealthCheck.Test,
Interval: time.Duration(container.HealthCheck.Interval) * time.Second,
Timeout: time.Duration(container.HealthCheck.Timeout) * time.Second,
StartPeriod: time.Duration(container.HealthCheck.StartPeriod) * time.Second,
Retries: container.HealthCheck.Retries,
}
}
// For Devices
devices := []conttype.DeviceMapping{}
for _, device := range container.Devices {
deviceSplit := strings.Split(device, ":")
devices = append(devices, conttype.DeviceMapping{
PathOnHost: deviceSplit[0],
PathInContainer: deviceSplit[1],
CgroupPermissions: "rwm", // This can be "r", "w", "m", or any combination
})
}
hostConfig.Devices = devices
networkingConfig := &network.NetworkingConfig{
EndpointsConfig: make(map[string]*network.EndpointSettings),
}
for netName, netConfig := range container.Networks {
networkingConfig.EndpointsConfig[netName] = &network.EndpointSettings{
Aliases: netConfig.Aliases,
IPAddress: netConfig.IPV4Address,
GlobalIPv6Address: netConfig.IPV6Address,
}
}
_, err = DockerClient.ContainerCreate(DockerContext, containerConfig, hostConfig, networkingConfig, nil, container.Name)
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Container", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Container creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
rollbackActions = append(rollbackActions, DockerServiceCreateRollback{
Action: "remove",
Type: "container",
Name: container.Name,
})
// add routes
for _, route := range container.Routes {
// check if route already exists
exists := false
for _, configRoute := range configRoutes {
if configRoute.Name == route.Name {
exists = true
break
}
}
if !exists {
configRoutes = append([]utils.ProxyRouteConfig{(utils.ProxyRouteConfig)(route)}, configRoutes...)
} else {
utils.Error("CreateService: Rolling back changes because of -- Route already exist", nil)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Route already exist")
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return errors.New("Route already exist")
}
}
// Write a response to the client
utils.Log(fmt.Sprintf("Container %s created", container.Name))
fmt.Fprintf(w, "Container %s created\n", container.Name)
flusher.Flush()
}
// re-order containers dpeneding on depends_on
startOrder, err := ReOrderServices(serviceRequest.Services)
if err != nil {
utils.Error("CreateService: Rolling back changes because of -- Container", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Container creation error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
// Start all the newly created containers
for _, container := range startOrder {
err = DockerClient.ContainerStart(DockerContext, container.Name, doctype.ContainerStartOptions{})
if err != nil {
utils.Error("CreateService: Start Container", err)
fmt.Fprintf(w, "[ERROR] Rolling back changes because of -- Container start error: "+err.Error())
flusher.Flush()
Rollback(rollbackActions, w, flusher)
return err
}
// Write a response to the client
utils.Log(fmt.Sprintf("Container %s started", container.Name))
fmt.Fprintf(w, "Container %s started\n", container.Name)
flusher.Flush()
}
// Save the route configs
config.HTTPConfig.ProxyConfig.Routes = configRoutes
utils.SaveConfigTofile(config)
utils.NeedsRestart = true
// After all operations
utils.Log("CreateService: Operation succeeded. SERVICE STARTED")
fmt.Fprintf(w, "[OPERATION SUCCEEDED]. SERVICE STARTED\n")
flusher.Flush()
return nil
}
func ReOrderServices(serviceMap map[string]ContainerCreateRequestContainer) ([]ContainerCreateRequestContainer, error) {
startOrder := []ContainerCreateRequestContainer{}

View file

@ -68,7 +68,7 @@ func ManageContainerRoute(w http.ResponseWriter, req *http.Request) {
case "unpause":
err = DockerClient.ContainerUnpause(DockerContext, container.ID)
case "recreate":
_, err = EditContainer(container.ID, container)
_, err = EditContainer(container.ID, container, false)
case "update":
out, errPull := DockerClient.ImagePull(DockerContext, imagename, doctype.ImagePullOptions{})
if errPull != nil {
@ -100,7 +100,7 @@ func ManageContainerRoute(w http.ResponseWriter, req *http.Request) {
utils.Log("Container Update - Image pulled " + imagename)
_, err = EditContainer(container.ID, container)
_, err = EditContainer(container.ID, container, false)
if err != nil {
utils.Error("Container Update - EditContainer", err)

View file

@ -20,7 +20,7 @@ func NewDBRoute(w http.ResponseWriter, req *http.Request) {
}
if(req.Method == "GET") {
costr, err := NewDB()
costr, err := NewDB(w, req)
if err != nil {
utils.Error("NewDB: Error while creating new DB", err)

View file

@ -37,9 +37,12 @@ func SecureContainerRoute(w http.ResponseWriter, req *http.Request) {
"cosmos-force-network-secured": status,
});
// change network mode to bridge in case it was set to container
container.HostConfig.NetworkMode = "bridge"
utils.Log("API: Set Force network secured "+status+" : " + containerName)
_, errEdit := EditContainer(container.ID, container)
_, errEdit := EditContainer(container.ID, container, false)
if errEdit != nil {
utils.Error("ContainerSecureEdit", errEdit)
utils.HTTPError(w, "Internal server error: " + errEdit.Error(), http.StatusInternalServerError, "DS003")

View file

@ -23,6 +23,7 @@ type ContainerForm struct {
Volumes []mount.Mount `json:"Volumes"`
// we make this a int so that we can ignore 0
Interactive int `json:"interactive"`
NetworkMode string `json:"networkMode"`
}
func UpdateContainerRoute(w http.ResponseWriter, req *http.Request) {
@ -119,8 +120,11 @@ func UpdateContainerRoute(w http.ResponseWriter, req *http.Request) {
container.Config.Tty = form.Interactive == 2
container.Config.OpenStdin = form.Interactive == 2
}
if(form.NetworkMode != "") {
container.HostConfig.NetworkMode = containerType.NetworkMode(form.NetworkMode)
}
_, err = EditContainer(container.ID, container)
_, err = EditContainer(container.ID, container, false)
if err != nil {
utils.Error("UpdateContainer: EditContainer", err)
utils.HTTPError(w, "Internal server error: "+err.Error(), http.StatusInternalServerError, "DS004")

View file

@ -31,6 +31,13 @@ func BootstrapAllContainersFromTags() []error {
return errors
}
func UnsecureContainer(container types.ContainerJSON) (string, error) {
RemoveLabels(container, []string{
"cosmos-force-network-secured",
});
return EditContainer(container.ID, container, false)
}
func BootstrapContainerFromTags(containerID string) error {
errD := Connect()
if errD != nil {
@ -71,6 +78,12 @@ func BootstrapContainerFromTags(containerID string) error {
if !isCosmosCon {
needsRestart, errCT = ConnectToSecureNetwork(container)
if errCT != nil {
utils.Warn("DockerContainerBootstrapConnectToSecureNetwork -- Cannot connect to network, removing force secure")
_, errUn := UnsecureContainer(container)
if errUn != nil {
utils.Fatal("DockerContainerBootstrapUnsecureContainer -- A broken container state is preventing Cosmos from functionning. Please remove the cosmos-force-secure label from the container "+container.Name+" manually", errUn)
return errCT
}
return errCT
}
if needsRestart {
@ -84,7 +97,12 @@ func BootstrapContainerFromTags(containerID string) error {
utils.Log(container.Name+": Disconnecting from bridge network")
errDisc := DockerClient.NetworkDisconnect(DockerContext, "bridge", containerID, true)
if errDisc != nil {
utils.Error("Docker Network Disconnect", errDisc)
utils.Warn("DockerContainerBootstrapDisconnectFromBridge -- Cannot disconnect from Bridge, removing force secure")
_, errUn := UnsecureContainer(container)
if errUn != nil {
utils.Fatal("DockerContainerBootstrapUnsecureContainer -- A broken container state is preventing Cosmos from functionning. Please remove the cosmos-force-secure label from the container "+container.Name+" manually", errUn)
return errDisc
}
return errDisc
}
}
@ -99,7 +117,7 @@ func BootstrapContainerFromTags(containerID string) error {
}
if(needsUpdate) {
_, errEdit := EditContainer(containerID, container)
_, errEdit := EditContainer(containerID, container, false)
if errEdit != nil {
utils.Error("Docker Boostrap, couldn't update container: ", errEdit)
return errEdit

View file

@ -4,7 +4,6 @@ import (
"context"
"errors"
"time"
"fmt"
"bufio"
"strings"
"github.com/azukaar/cosmos-server/src/utils"
@ -82,11 +81,8 @@ func Connect() error {
return nil
}
func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string, error) {
utils.Debug("VOLUMES:" + fmt.Sprintf("%v", newConfig.HostConfig.Mounts))
if(oldContainerID != "") {
func EditContainer(oldContainerID string, newConfig types.ContainerJSON, noLock bool) (string, error) {
if(oldContainerID != "" && !noLock) {
// no need to re-lock if we are reverting
DockerNetworkLock <- true
defer func() {
@ -99,6 +95,17 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
return "", errD
}
}
if(newConfig.HostConfig.NetworkMode != "bridge" &&
newConfig.HostConfig.NetworkMode != "default" &&
newConfig.HostConfig.NetworkMode != "host" &&
newConfig.HostConfig.NetworkMode != "none") {
if(!HasLabel(newConfig, "cosmos-force-network-mode")) {
AddLabels(newConfig, map[string]string{"cosmos-force-network-mode": string(newConfig.HostConfig.NetworkMode)})
} else {
newConfig.HostConfig.NetworkMode = container.NetworkMode(GetLabel(newConfig, "cosmos-force-network-mode"))
}
}
newName := newConfig.Name
oldContainer := newConfig
@ -112,8 +119,6 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
// https://godoc.org/github.com/docker/docker/api/types#ContainerJSON
oldContainer, err = DockerClient.ContainerInspect(DockerContext, oldContainerID)
utils.Debug("OLD VOLUMES:" + fmt.Sprintf("%v", oldContainer.HostConfig.Mounts))
if err != nil {
return "", err
}
@ -138,7 +143,6 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
// if no name, use the same one, that will force Docker to create a hostname if not set
newName = oldContainer.Name
newConfig.Config.Hostname = newName
// stop and remove container
stopError := DockerClient.ContainerStop(DockerContext, oldContainerID, container.StopOptions{})
@ -168,6 +172,16 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
utils.Log("EditContainer - Revert started")
}
// only force hostname if network is bridge or default, otherwise it will fail
if newConfig.HostConfig.NetworkMode == "bridge" || newConfig.HostConfig.NetworkMode == "default" {
newConfig.Config.Hostname = newName
} else {
// if not, remove hostname because otherwise it will try to keep the old one
newConfig.Config.Hostname = ""
// IDK Docker is weird, if you don't erase this it will break
newConfig.Config.ExposedPorts = nil
}
// recreate container with new informations
createResponse, createError := DockerClient.ContainerCreate(
DockerContext,
@ -177,7 +191,10 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
nil,
newName,
)
if createError != nil {
utils.Error("EditContainer - Failed to create container", createError)
}
utils.Log("EditContainer - Container recreated. Re-connecting networks " + createResponse.ID)
// is force secure
@ -202,6 +219,10 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
runError := DockerClient.ContainerStart(DockerContext, createResponse.ID, types.ContainerStartOptions{})
if runError != nil {
utils.Error("EditContainer - Failed to run container", runError)
}
if createError != nil || runError != nil {
if(oldContainerID == "") {
if(createError == nil) {
@ -217,12 +238,17 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
if(createError == nil) {
utils.Log("EditContainer - Killing new broken container")
// attempt kill
DockerClient.ContainerKill(DockerContext, oldContainerID, "")
DockerClient.ContainerKill(DockerContext, createResponse.ID, "")
// attempt remove in case created state
DockerClient.ContainerRemove(DockerContext, oldContainerID, types.ContainerRemoveOptions{})
DockerClient.ContainerRemove(DockerContext, createResponse.ID, types.ContainerRemoveOptions{})
}
utils.Log("EditContainer - Reverting...")
// attempt to restore container
restored, restoreError := EditContainer("", oldContainer)
restored, restoreError := EditContainer("", oldContainer, false)
if restoreError != nil {
utils.Error("EditContainer - Failed to restore container", restoreError)
@ -245,12 +271,48 @@ func EditContainer(oldContainerID string, newConfig types.ContainerJSON) (string
return restored, errors.New("Failed to edit container, but restored to previous state. Error was: " + errorWas)
}
}
// Recreating dependant containers
utils.Debug("Unlocking EDIT Container")
if oldContainerID != "" {
RecreateDepedencies(oldContainerID)
}
utils.Log("EditContainer - Container started. All done! " + createResponse.ID)
return createResponse.ID, nil
}
func RecreateDepedencies(containerID string) {
containers, err := ListContainers()
if err != nil {
utils.Error("RecreateDepedencies", err)
return
}
for _, container := range containers {
if container.ID == containerID {
continue
}
fullContainer, err := DockerClient.ContainerInspect(DockerContext, container.ID)
if err != nil {
utils.Error("RecreateDepedencies", err)
continue
}
// check if network mode contains containerID
if strings.Contains(string(fullContainer.HostConfig.NetworkMode), containerID) {
utils.Log("RecreateDepedencies - Recreating " + container.Names[0])
_, err := EditContainer(container.ID, fullContainer, true)
if err != nil {
utils.Error("RecreateDepedencies - Failed to update - ", err)
}
}
}
}
func ListContainers() ([]types.Container, error) {
errD := Connect()
if errD != nil {
@ -397,7 +459,7 @@ func CheckUpdatesAvailable() map[string]bool {
if needsUpdate && IsLabel(fullContainer, "cosmos-auto-update") {
utils.Log("Downlaoded new update for " + container.Image + " ready to install")
_, err := EditContainer(container.ID, fullContainer)
_, err := EditContainer(container.ID, fullContainer, false)
if err != nil {
utils.Error("CheckUpdatesAvailable - Failed to update - ", err)
} else {

View file

@ -4,6 +4,9 @@ import (
"github.com/azukaar/cosmos-server/src/utils"
"io"
"os"
"net/http"
// "github.com/docker/docker/client"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types"
@ -18,13 +21,13 @@ type VolumeMount struct {
Volume *types.Volume
}
func NewDB() (string, error) {
func NewDB(w http.ResponseWriter, req *http.Request) (string, error) {
id := utils.GenerateRandomString(3)
mongoUser := "cosmos-" + utils.GenerateRandomString(5)
mongoPass := utils.GenerateRandomString(24)
monHost := "cosmos-mongo-" + id
imageName := "mongo:latest"
imageName := "mongo:5"
// if CPU is missing AVX, use 4.4
if runtime.GOARCH == "amd64" && !cpu.X86.HasAVX {
@ -32,28 +35,36 @@ func NewDB() (string, error) {
imageName = "mongo:4.4"
}
err := RunContainer(
imageName,
monHost,
[]string{
service := DockerServiceCreateRequest{
Services: map[string]ContainerCreateRequestContainer {},
}
service.Services[monHost] = ContainerCreateRequestContainer{
Name: monHost,
Image: imageName,
RestartPolicy: "always",
Environment: []string{
"MONGO_INITDB_ROOT_USERNAME=" + mongoUser,
"MONGO_INITDB_ROOT_PASSWORD=" + mongoPass,
},
[]VolumeMount{
Labels: map[string]string{
"cosmos-force-network-secured": "true",
},
Volumes: []mount.Mount{
{
Destination: "/data/db",
Volume: &types.Volume{
Name: "cosmos-mongo-data-" + id,
},
Type: mount.TypeVolume,
Source: "cosmos-mongo-data-" + id,
Target: "/data/db",
},
{
Destination: "/data/configdb",
Volume: &types.Volume{
Name: "cosmos-mongo-config-" + id,
},
Type: mount.TypeVolume,
Source: "cosmos-mongo-config-" + id,
Target: "/data/configdb",
},
},
)
};
err := CreateService(w, req, service)
if err != nil {
return "", err
@ -87,54 +98,13 @@ func RunContainer(imagename string, containername string, inputEnv []string, vol
mounts = append(mounts, mount)
}
// Define a PORT opening
// newport, err := natting.NewPort("tcp", port)
// if err != nil {
// fmt.Println("Unable to create docker port")
// return err
// }
// Configured hostConfig:
// https://godoc.org/github.com/docker/docker/api/types/container#HostConfig
hostConfig := &container.HostConfig{
// PortBindings: natting.PortMap{
// newport: []natting.PortBinding{
// {
// HostIP: "0.0.0.0",
// HostPort: port,
// },
// },
// },
Mounts : mounts,
RestartPolicy: container.RestartPolicy{
Name: "always",
},
// LogConfig: container.LogConfig{
// Type: "json-file",
// Config: map[string]string{},
// },
}
// Define Network config
// https://godoc.org/github.com/docker/docker/api/types/network#NetworkingConfig
// networkConfig := &network.NetworkingConfig{
// EndpointsConfig: map[string]*network.EndpointSettings{},
// }
// gatewayConfig := &network.EndpointSettings{
// Gateway: "gatewayname",
// }
// networkConfig.EndpointsConfig["bridge"] = gatewayConfig
// Define ports to be exposed (has to be same as hostconfig.portbindings.newport)
// exposedPorts := map[natting.Port]struct{}{
// newport: struct{}{},
// }
// Configuration
// https://godoc.org/github.com/docker/docker/api/types/container#Config
config := &container.Config{
Image: imagename,
Env: inputEnv,
@ -145,9 +115,6 @@ func RunContainer(imagename string, containername string, inputEnv []string, vol
// ExposedPorts: exposedPorts,
}
//archi := runtime.GOARCH
// Creating the actual container. This is "nil,nil,nil" in every example.
cont, err := DockerClient.ContainerCreate(
DockerContext,
config,
@ -162,7 +129,6 @@ func RunContainer(imagename string, containername string, inputEnv []string, vol
return err
}
// Run the actual container
DockerClient.ContainerStart(DockerContext, cont.ID, types.ContainerStartOptions{})
utils.Log("Container created " + cont.ID)

View file

@ -190,7 +190,7 @@ func StartServer() {
// need rewrite bc it catches too many things and prevent
// client to be notified of the error
// router.Use(middleware.Recoverer)
router.Use(middleware.Logger)
router.Use(utils.SetSecurityHeaders)

View file

@ -123,7 +123,7 @@ func GetFavicon(w http.ResponseWriter, req *http.Request) {
iconURL := icon.URL
u, err := url.Parse(siteurl)
if err != nil {
utils.Error("FaviconFetch failed to parse ", err)
utils.Debug("FaviconFetch failed to parse " + err.Error())
continue
}
@ -146,21 +146,21 @@ func GetFavicon(w http.ResponseWriter, req *http.Request) {
}
}
utils.Log("Favicon Trying to fetch " + iconURL)
utils.Debug("Favicon Trying to fetch " + iconURL)
// Fetch the favicon
resp, err := http.Get(iconURL)
if err != nil {
utils.Error("FaviconFetch", err)
utils.Debug("FaviconFetch" + err.Error())
continue
}
// check if 200 and if image
if resp.StatusCode != 200 {
utils.Error("FaviconFetch - " + iconURL + " - not 200 ", nil)
utils.Debug("FaviconFetch - " + iconURL + " - not 200 ")
continue
} else if !strings.Contains(resp.Header.Get("Content-Type"), "image") && !strings.Contains(resp.Header.Get("Content-Type"), "octet-stream") {
utils.Error("FaviconFetch - " + iconURL + " - not image ", nil)
utils.Debug("FaviconFetch - " + iconURL + " - not image ")
continue
} else {
utils.Log("Favicon found " + iconURL)
@ -168,7 +168,7 @@ func GetFavicon(w http.ResponseWriter, req *http.Request) {
// Cache the response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
utils.Error("FaviconFetch - cant read ", err)
utils.Debug("FaviconFetch - cant read " + err.Error())
continue
}

View file

@ -85,13 +85,13 @@ func NewInstallRoute(w http.ResponseWriter, req *http.Request) {
} else if (request.MongoDBMode == "Create") {
utils.Log("NewInstall: Create DB")
newConfig.DisableUserManagement = false
strco, err := docker.NewDB()
strco, err := docker.NewDB(w, req)
if err != nil {
utils.Error("NewInstall: Error creating MongoDB", err)
utils.HTTPError(w, "New Install: Error creating MongoDB " + err.Error(),
http.StatusInternalServerError, "NI001")
return
}
}
newConfig.MongoDB = strco
utils.SaveConfigTofile(newConfig)
utils.LoadBaseMainConfig(newConfig)