diff --git a/changelog.md b/changelog.md
index e2aec62..f5cbd3a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,17 @@
+## Version 0.1.16
+
+ - Fix search
+ - Fix bug where containers would lose their networks after being edited
+ - Self-heal secure network configuration
+ - Auto disconnect from orphan networks
+ - Prevent bootstrapping from creating orphan networks
+ - Monitor Docker and self-heal when docker daemon dies
+ - Recreate lost secure networks (ex. when resetting Cosmos)
+
+
+
## Version 0.1.15
+
- Ports is now freetype, in case container does not expose any
- Container picker now tries to pick the best port as default
- Hostname now default to container name
diff --git a/client/src/pages/config/users/proxyman.jsx b/client/src/pages/config/users/proxyman.jsx
index 8e403fa..b0bb42d 100644
--- a/client/src/pages/config/users/proxyman.jsx
+++ b/client/src/pages/config/users/proxyman.jsx
@@ -62,7 +62,6 @@ const ProxyManagement = () => {
},
};
setConfig(con);
- setNeedSave(true);
return con;
}
@@ -86,12 +85,14 @@ const ProxyManagement = () => {
routes[key] = routes[key-1];
routes[key-1] = tmp;
updateRoutes(routes);
+ setNeedSave(true);
}
}
function deleteRoute(key) {
routes.splice(key, 1);
updateRoutes(routes);
+ setNeedSave(true);
}
function down(key) {
@@ -100,6 +101,7 @@ const ProxyManagement = () => {
routes[key] = routes[key+1];
routes[key+1] = tmp;
updateRoutes(routes);
+ setNeedSave(true);
}
}
@@ -136,6 +138,7 @@ const ProxyManagement = () => {
AuthEnabled: false,
});
updateRoutes(routes);
+ setNeedSave(true);
}}>Create
diff --git a/client/src/pages/config/users/usermanagement.jsx b/client/src/pages/config/users/usermanagement.jsx
index 7a8bb08..a2f0352 100644
--- a/client/src/pages/config/users/usermanagement.jsx
+++ b/client/src/pages/config/users/usermanagement.jsx
@@ -40,7 +40,6 @@ const UserManagement = () => {
setIsLoading(true);
API.users.list()
.then(data => {
- console.log(data);
setRows(data.data);
setIsLoading(false);
})
diff --git a/client/src/pages/servapps/servapps.jsx b/client/src/pages/servapps/servapps.jsx
index 2c64482..3946dc2 100644
--- a/client/src/pages/servapps/servapps.jsx
+++ b/client/src/pages/servapps/servapps.jsx
@@ -45,7 +45,6 @@ const ServeApps = () => {
}
const testRoute = (route) => {
- console.log(newRoute)
try {
ValidateRoute.validateSync(route);
} catch (e) {
@@ -206,7 +205,7 @@ const ServeApps = () => {
- {serveApps && serveApps.filter(app => search.length < 2 || app.Names[0].includes(search)).map((app) => {
+ {serveApps && serveApps.filter(app => search.length < 2 || app.Names[0].toLowerCase().includes(search.toLowerCase())).map((app) => {
return
-
}>
diff --git a/client/src/routes/MainRoutes.jsx b/client/src/routes/MainRoutes.jsx
index f6e4188..049a533 100644
--- a/client/src/routes/MainRoutes.jsx
+++ b/client/src/routes/MainRoutes.jsx
@@ -33,7 +33,7 @@ const MainRoutes = {
element:
},
{
- path: '/ui/',
+ path: '/ui',
element:
},
{
diff --git a/client/src/themes/index.jsx b/client/src/themes/index.jsx
index 03ef80b..c288b03 100644
--- a/client/src/themes/index.jsx
+++ b/client/src/themes/index.jsx
@@ -18,7 +18,6 @@ export default function ThemeCustomization({ children }) {
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ?
'dark' : 'light');
- console.log(theme)
// eslint-disable-next-line react-hooks/exhaustive-deps
const themeTypography = Typography(`'Public Sans', sans-serif`);
diff --git a/client/src/themes/theme/index.jsx b/client/src/themes/theme/index.jsx
index 89f8540..73f8016 100644
--- a/client/src/themes/theme/index.jsx
+++ b/client/src/themes/theme/index.jsx
@@ -3,7 +3,6 @@
import { purple, pink, deepPurple } from '@mui/material/colors';
const Theme = (colors) => {
- console.log(colors)
const { blue, red, gold, cyan, green, grey } = colors;
const greyColors = {
0: grey[0],
diff --git a/package.json b/package.json
index 74b2b57..303c9af 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cosmos-server",
- "version": "0.1.15",
+ "version": "0.1.16",
"description": "",
"main": "test-server.js",
"bugs": {
@@ -57,7 +57,7 @@
"build": " sh build.sh",
"dev": "npm run build && npm run start",
"dockerdevbuild": "sh build.sh && npm run client-build && docker build --tag cosmos-dev .",
- "dockerdevrun": "docker stop cosmos-dev; docker rm cosmos-dev; docker run -d -p 80:80 -p 443:443 -e DOCKER_HOST=tcp://host.docker.internal:2375 -e COSMOS_HOSTNAME=localhost -e COSMOS_MONGODB=$MONGODB -e COSMOS_LOG_LEVEL=DEBUG --restart=unless-stopped --name cosmos-dev cosmos-dev",
+ "dockerdevrun": "docker stop cosmos-dev; docker rm cosmos-dev; docker run -d -p 80:80 -p 443:443 -e DOCKER_HOST=tcp://host.docker.internal:2375 -e COSMOS_HOSTNAME=localhost -e COSMOS_MONGODB=$MONGODB -e COSMOS_LOG_LEVEL=DEBUG --restart=unless-stopped -h cosmos-dev --name cosmos-dev cosmos-dev",
"dockerdev": "npm run dockerdevbuild && npm run dockerdevrun"
},
"eslintConfig": {
diff --git a/sponsors.js b/sponsors.js
index 11925b2..8c4b875 100644
--- a/sponsors.js
+++ b/sponsors.js
@@ -56,18 +56,21 @@ const sponsorsGenerate = async () => {
function changelog() {
// get the changes from last commit message
const { execSync } = require('child_process')
- const commitMessage = execSync('git log -1 --pretty=%B').toString()
- if(!commitMessage.toLocaleLowerCase().startsWith('[release]')) {
+ let commitMessage = execSync('git log -1 --pretty=%B').toString()
+
+ if(!commitMessage.startsWith('[release]')) {
console.log('Not a release commit, skipping changelog update')
return
}
const version = packageJson.version
+
+ commitMessage = commitMessage.replace('[release]', 'Version')
// open changelog.md
const changelog = fs.readFileSync('./changelog.md', 'utf8')
// add the new changes to the top of the changelog
- const newChangelog = `## Version ${version} \n ${commitMessage}\n\n${changelog}`
+ const newChangelog = `## ${commitMessage}\n\n${changelog}`
// write the new changelog
fs.writeFileSync('./changelog.md', newChangelog)
@@ -84,4 +87,4 @@ function changelog() {
}
sponsorsGenerate()
-changelog();
\ No newline at end of file
+// changelog();
\ No newline at end of file
diff --git a/src/CRON.go b/src/CRON.go
index 01ff921..f1ef444 100644
--- a/src/CRON.go
+++ b/src/CRON.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"net/http"
"github.com/azukaar/cosmos-server/src/utils"
+ // "github.com/azukaar/cosmos-server/src/docker"
"os"
"path/filepath"
"encoding/json"
@@ -64,6 +65,8 @@ func checkVersion() {
}
func CRON() {
- gocron.Every(1).Day().At("00:00").Do(checkVersion)
- <-gocron.Start()
+ go func() {
+ gocron.Every(1).Day().At("00:00").Do(checkVersion)
+ <-gocron.Start()
+ }()
}
\ No newline at end of file
diff --git a/src/config.go b/src/config.go
index cf4577c..d9fe765 100644
--- a/src/config.go
+++ b/src/config.go
@@ -24,6 +24,7 @@ func LoadConfig() utils.Config {
decoder := json.NewDecoder(file)
config := utils.Config{}
err = decoder.Decode(&config)
+
// check file is not empty
if err != nil {
// check error is not empty
@@ -48,6 +49,9 @@ func LoadConfig() utils.Config {
}
utils.LoadBaseMainConfig(config)
+
+ configJson, _ := json.MarshalIndent(config, "", " ")
+ utils.Debug("Loaded Configuration " + (string)(configJson))
return config
}
\ No newline at end of file
diff --git a/src/docker/api_secureContainer.go b/src/docker/api_secureContainer.go
index 0ee598b..c63ca25 100644
--- a/src/docker/api_secureContainer.go
+++ b/src/docker/api_secureContainer.go
@@ -21,7 +21,7 @@ func SecureContainerRoute(w http.ResponseWriter, req *http.Request) {
if(req.Method == "GET") {
container, err := DockerClient.ContainerInspect(DockerContext, containerName)
if err != nil {
- utils.Error("ContainerSecure", err)
+ utils.Error("ContainerSecureInscpect", err)
utils.HTTPError(w, "Internal server error: " + err.Error(), http.StatusInternalServerError, "DS002")
return
}
@@ -34,7 +34,7 @@ func SecureContainerRoute(w http.ResponseWriter, req *http.Request) {
_, errEdit := EditContainer(container.ID, container)
if errEdit != nil {
- utils.Error("ContainerSecure", errEdit)
+ utils.Error("ContainerSecureEdit", errEdit)
utils.HTTPError(w, "Internal server error: " + err.Error(), http.StatusInternalServerError, "DS003")
return
}
diff --git a/src/docker/bootstrap.go b/src/docker/bootstrap.go
index 87efc46..c4c3475 100644
--- a/src/docker/bootstrap.go
+++ b/src/docker/bootstrap.go
@@ -3,6 +3,7 @@ package docker
import (
"github.com/azukaar/cosmos-server/src/utils"
"github.com/docker/docker/api/types"
+ "os"
)
func BootstrapAllContainersFromTags() []error {
@@ -30,18 +31,27 @@ func BootstrapAllContainersFromTags() []error {
return errors
}
-
func BootstrapContainerFromTags(containerID string) error {
errD := Connect()
if errD != nil {
return errD
}
+ selfContainer := types.ContainerJSON{}
+ if os.Getenv("HOSTNAME") != "" {
+ var errS error
+ selfContainer, errS = DockerClient.ContainerInspect(DockerContext, os.Getenv("HOSTNAME"))
+ if errS != nil {
+ utils.Error("DockerContainerBootstrapSelfInspect", errS)
+ return errS
+ }
+ }
+
utils.Log("Bootstrap Container From Tags: " + containerID)
container, err := DockerClient.ContainerInspect(DockerContext, containerID)
if err != nil {
- utils.Error("Docker Container Bootstrap Inspect", err)
+ utils.Error("DockerContainerBootstrapInspect", err)
return err
}
@@ -51,12 +61,10 @@ func BootstrapContainerFromTags(containerID string) error {
utils.Log(container.Name+": Checking Force network secured")
// check if connected to bridge and to a cosmos network
- isCon, errC := IsConnectedToNetwork(container, "bridge")
- isCosmosCon, _ := IsConnectedToASecureCosmosNetwork(container)
+ isCon := IsConnectedToNetwork(container, "bridge")
+ isCosmosCon, _ := IsConnectedToASecureCosmosNetwork(selfContainer, container)
- if errC != nil {
- return errC
- } else if isCon || !isCosmosCon {
+ if isCon || !isCosmosCon {
utils.Log(container.Name+": Needs isolating on a secured network")
needsRestart := false
var errCT error
@@ -66,7 +74,7 @@ func BootstrapContainerFromTags(containerID string) error {
return errCT
}
if needsRestart {
- utils.Log(container.Name+": Will connect to new network after restart")
+ utils.Log(container.Name+": Will restart to apply changes")
needsUpdate = true
} else {
utils.Log(container.Name+": Connected to new network")
diff --git a/src/docker/docker.go b/src/docker/docker.go
index 1c12f57..9102784 100644
--- a/src/docker/docker.go
+++ b/src/docker/docker.go
@@ -3,13 +3,12 @@ package docker
import (
"context"
"errors"
-
+ "time"
"github.com/azukaar/cosmos-server/src/utils"
"github.com/docker/docker/client"
// natting "github.com/docker/go-connections/nat"
"github.com/docker/docker/api/types/container"
- // network "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types"
)
@@ -37,6 +36,18 @@ func getIdFromName(name string) (string, error) {
var DockerIsConnected = false
func Connect() error {
+ if DockerClient != nil {
+ // check if connection is still alive
+ ping, err := DockerClient.Ping(DockerContext)
+ if ping.APIVersion != "" && err == nil {
+ DockerIsConnected = true
+ return nil
+ } else {
+ DockerIsConnected = false
+ DockerClient = nil
+ utils.Error("Docker Connection died, will try to connect again", err)
+ }
+ }
if DockerClient == nil {
ctx := context.Background()
client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
@@ -69,11 +80,17 @@ func Connect() error {
}
func EditContainer(containerID string, newConfig types.ContainerJSON) (string, error) {
+ DockerNetworkLock <- true
+ defer func() {
+ <-DockerNetworkLock
+ utils.Debug("Unlocking EDIT Container")
+ }()
+
errD := Connect()
if errD != nil {
return "", errD
}
- utils.Log("Container updating " + containerID)
+ utils.Log("EditContainer - Container updating " + containerID)
// get container informations
// https://godoc.org/github.com/docker/docker/api/types#ContainerJSON
@@ -98,7 +115,19 @@ func EditContainer(containerID string, newConfig types.ContainerJSON) (string, e
return "", removeError
}
- utils.Log("Container stopped " + containerID)
+ // wait for container to be destroyed
+ //
+ for {
+ _, err := DockerClient.ContainerInspect(DockerContext, containerID)
+ if err != nil {
+ break
+ } else {
+ utils.Log("EditContainer - Waiting for container to be destroyed")
+ time.Sleep(1 * time.Second)
+ }
+ }
+
+ utils.Log("EditContainer - Container stopped " + containerID)
// recreate container with new informations
createResponse, createError := DockerClient.ContainerCreate(
@@ -110,24 +139,33 @@ func EditContainer(containerID string, newConfig types.ContainerJSON) (string, e
newName,
)
+ // re-connect to networks
+ for networkName, _ := range oldContainer.NetworkSettings.Networks {
+ errNet := ConnectToNetworkSync(networkName, createResponse.ID)
+ if errNet != nil {
+ utils.Error("EditContainer - Failed to connect to network " + networkName, errNet)
+ } else {
+ utils.Debug("EditContainer - New Container connected to network " + networkName)
+ }
+ }
+
runError := DockerClient.ContainerStart(DockerContext, createResponse.ID, types.ContainerStartOptions{})
if runError != nil {
return "", runError
}
- utils.Log("Container recreated " + createResponse.ID)
+ utils.Log("EditContainer - Container recreated " + createResponse.ID)
if createError != nil {
// attempt to restore container
_, restoreError := DockerClient.ContainerCreate(DockerContext, oldContainer.Config, nil, nil, nil, oldContainer.Name)
if restoreError != nil {
- utils.Error("Failed to restore Docker Container after update failure", restoreError)
+ utils.Error("EditContainer - Failed to restore Docker Container after update failure", restoreError)
}
return "", createError
}
-
return createResponse.ID, nil
}
@@ -174,6 +212,14 @@ func AddLabels(containerConfig types.ContainerJSON, labels map[string]string) er
return nil
}
+func RemoveLabels(containerConfig types.ContainerJSON, labels []string) error {
+ for _, label := range labels {
+ delete(containerConfig.Config.Labels, label)
+ }
+
+ return nil
+}
+
func IsLabel(containerConfig types.ContainerJSON, label string) bool {
if containerConfig.Config.Labels[label] == "true" {
return true
diff --git a/src/docker/events.go b/src/docker/events.go
index 2235985..9d497b9 100644
--- a/src/docker/events.go
+++ b/src/docker/events.go
@@ -25,11 +25,25 @@ func DockerListenEvents() error {
return
}
utils.Error("Docker Event Error", err)
+ // Check connection
+ errD := Connect()
+ if errD != nil {
+ utils.Fatal("Docker connection died, couldn't recover... Restarting", errD)
+ }
+ msgs, errs = DockerClient.Events(context.Background(), types.EventsOptions{})
+
case msg := <-msgs:
utils.Debug("Docker Event: " + msg.Type + " " + msg.Action + " " + msg.Actor.ID)
if msg.Type == "container" && msg.Action == "start" {
onDockerCreated(msg.Actor.ID)
}
+ // on container destroy and network disconnect
+ if msg.Type == "container" && msg.Action == "destroy" {
+ onDockerDestroyed(msg.Actor.ID)
+ }
+ if msg.Type == "network" && msg.Action == "disconnect" {
+ onNetworkDisconnect(msg.Actor.ID)
+ }
}
}
}()
@@ -40,4 +54,14 @@ func DockerListenEvents() error {
func onDockerCreated(containerID string) {
utils.Debug("onDockerCreated: " + containerID)
BootstrapContainerFromTags(containerID)
+}
+
+func onDockerDestroyed(containerID string) {
+ utils.Debug("onDockerDestroyed: " + containerID)
+ NetworkCleanUp()
+}
+
+func onNetworkDisconnect(networkID string) {
+ utils.Debug("onNetworkDisconnect: " + networkID)
+ NetworkCleanUp()
}
\ No newline at end of file
diff --git a/src/docker/network.go b/src/docker/network.go
index ed78d4b..2d71105 100644
--- a/src/docker/network.go
+++ b/src/docker/network.go
@@ -2,6 +2,8 @@ package docker
import (
"os"
+ "time"
+ "errors"
"github.com/azukaar/cosmos-server/src/utils"
@@ -10,6 +12,9 @@ import (
natting "github.com/docker/go-connections/nat"
)
+// use a semaphore lock
+var DockerNetworkLock = make(chan bool, 1)
+
func CreateCosmosNetwork() (string, error) {
// check if network exists already
networks, err := DockerClient.NetworkList(DockerContext, types.NetworkListOptions{})
@@ -35,25 +40,27 @@ func CreateCosmosNetwork() (string, error) {
utils.Log("Creating new secure network: " + newNeworkName)
// create network
- _, err = DockerClient.NetworkCreate(DockerContext, newNeworkName, types.NetworkCreate{
+ newNetHan, err := DockerClient.NetworkCreate(DockerContext, newNeworkName, types.NetworkCreate{
Attachable: true,
})
+ utils.Debug("New network created: " + newNeworkName + " with id " + newNetHan.ID)
+
if err != nil {
utils.Error("Docker Network Create", err)
return "", err
}
//if running in Docker, connect to main network
- utils.Debug("HOSTNAME: " + os.Getenv("HOSTNAME"))
- if os.Getenv("HOSTNAME") != "" {
- err := DockerClient.NetworkConnect(DockerContext, newNeworkName, os.Getenv("HOSTNAME"), &network.EndpointSettings{})
+ // utils.Debug("HOSTNAME: " + os.Getenv("HOSTNAME"))
+ // if os.Getenv("HOSTNAME") != "" {
+ // err := DockerClient.NetworkConnect(DockerContext, newNeworkName, os.Getenv("HOSTNAME"), &network.EndpointSettings{})
- if err != nil {
- utils.Error("Docker Network Connect", err)
- return "", err
- }
- }
+ // if err != nil {
+ // utils.Error("Docker Network Connect", err)
+ // return "", err
+ // }
+ // }
return newNeworkName, nil
}
@@ -65,41 +72,53 @@ func ConnectToSecureNetwork(containerConfig types.ContainerJSON) (bool, error) {
return false, errD
}
+ needsRestart := false
+ netName := ""
+
if(!HasLabel(containerConfig, "cosmos-network-name")) {
newNetwork, errNC := CreateCosmosNetwork()
if errNC != nil {
- utils.Error("Docker Network Create", errNC)
+ utils.Error("DockerSecureNetworkCreate", errNC)
return false, errNC
}
- utils.Log("Connected to new secure network for container: " + newNetwork)
-
+ utils.Log("Added label to new secure network for container: " + newNetwork)
+
AddLabels(containerConfig, map[string]string{
"cosmos-network-name": newNetwork,
})
-
- return true, nil
+
+ needsRestart = true
+ netName = newNetwork
+ } else {
+ netName = GetLabel(containerConfig, "cosmos-network-name")
+
+ //if network doesn't exists
+ _, err := DockerClient.NetworkInspect(DockerContext, netName, types.NetworkInspectOptions{})
+ if err != nil {
+ utils.Error("Container tries to connect to a non existing Cosmos network, resetting", err)
+ RemoveLabels(containerConfig, []string{"cosmos-network-name"})
+ return ConnectToSecureNetwork(containerConfig)
+ }
+
+ // else check if already connected
+ if(IsConnectedToNetwork(containerConfig, netName)) {
+ return false, nil
+ }
}
- netName := GetLabel(containerConfig, "cosmos-network-name")
-
- connected, err := IsConnectedToNetwork(containerConfig, netName)
- if err != nil {
- utils.Error("IsConnectedToNetwork", err)
- return false, err
- }
- if(connected) {
- return false, nil
- }
-
- errCo := DockerClient.NetworkConnect(DockerContext, netName, containerConfig.ID, &network.EndpointSettings{})
+ // at this point network is created and container is not connected to it
+
+ errCo := ConnectToNetworkSync(netName, containerConfig.ID)
+
+ utils.Log("Created and connected to secure network: " + netName)
if errCo != nil {
- utils.Error("Docker Network Connect", errCo)
+ utils.Error("ConnectToSecureNetworkConnect", errCo)
return false, errCo
}
- return false, nil
+ return needsRestart, nil
}
func UnexposeAllPorts(container *types.ContainerJSON) error {
@@ -120,22 +139,21 @@ func GetAllPorts(container types.ContainerJSON) []string {
return ports
}
-func IsConnectedToNetwork(containerConfig types.ContainerJSON, networkName string) (bool, error) {
+func IsConnectedToNetwork(containerConfig types.ContainerJSON, networkName string) bool {
if(containerConfig.NetworkSettings == nil) {
- utils.Error("IsConnectedToNetwork: NetworkSettings is nil", nil)
- return false, nil
+ return false
}
for name, _ := range containerConfig.NetworkSettings.Networks {
if name == networkName {
- return true, nil
+ return true
}
}
- return false, nil
+ return false
}
-func IsConnectedToASecureCosmosNetwork(containerConfig types.ContainerJSON) (bool, error) {
+func IsConnectedToASecureCosmosNetwork(self types.ContainerJSON, containerConfig types.ContainerJSON) (bool, error) {
if(containerConfig.NetworkSettings == nil) {
utils.Error("IsConnectedToASecureCosmosNetwork: NetworkSettings is nil", nil)
return false, nil
@@ -148,12 +166,13 @@ func IsConnectedToASecureCosmosNetwork(containerConfig types.ContainerJSON) (boo
for name, _ := range containerConfig.NetworkSettings.Networks {
if name == GetLabel(containerConfig, "cosmos-network-name") {
if os.Getenv("HOSTNAME") != "" {
- // TODO: Check if connected to network first
- DockerClient.NetworkConnect(DockerContext, name, os.Getenv("HOSTNAME"), &network.EndpointSettings{})
- // if err != nil {
- // utils.Error("Docker Network Connect EXISTING ", err)
- // return false, err
- // }
+ if(!IsConnectedToNetwork(self, name)) {
+ err := DockerClient.NetworkConnect(DockerContext, name, os.Getenv("HOSTNAME"), &network.EndpointSettings{})
+ if err != nil {
+ utils.Error("Docker Network Connect EXISTING ", err)
+ return false, err
+ }
+ }
}
return true, nil
}
@@ -161,3 +180,124 @@ func IsConnectedToASecureCosmosNetwork(containerConfig types.ContainerJSON) (boo
return false, nil
}
+
+func ConnectToNetworkIfNotConnected(containerConfig types.ContainerJSON, networkName string) error {
+ if(IsConnectedToNetwork(containerConfig, networkName)) {
+ return nil
+ }
+ return ConnectToNetworkSync(networkName, containerConfig.ID)
+}
+
+func ConnectToNetworkSync(networkName string, containerID string) error {
+ err := DockerClient.NetworkConnect(DockerContext, networkName, containerID, &network.EndpointSettings{})
+ if err != nil {
+ utils.Error("ConnectToNetworkSync", err)
+ return err
+ }
+
+ // wait for connection to be established
+ retries := 10
+ for {
+ newContainer, err := DockerClient.ContainerInspect(DockerContext, containerID)
+ if err != nil {
+ utils.Error("ConnectToNetworkSync", err)
+ return err
+ }
+
+ if(IsConnectedToNetwork(newContainer, networkName)) {
+ break
+ }
+
+ retries--
+ if retries == 0 {
+ return errors.New("ConnectToNetworkSync: Timeout")
+ }
+ time.Sleep(500 * time.Millisecond)
+ }
+
+
+ utils.Log("Connected "+containerID+" to network: " + networkName)
+
+ return nil
+}
+
+func NetworkCleanUp() {
+ DockerNetworkLock <- true
+ defer func() { <-DockerNetworkLock }()
+
+ config := utils.GetMainConfig()
+
+ utils.Log("Cleaning up orphan networks...")
+
+ // list every network
+ networks, err := DockerClient.NetworkList(DockerContext, types.NetworkListOptions{})
+ if err != nil {
+ utils.Error("NetworkCleanUpList", err)
+ return
+ }
+
+
+ // check if network is empty or has only self as container
+ for _, networkHollow := range networks {
+ utils.Debug("Checking network: " + networkHollow.Name)
+
+ if(networkHollow.Name == "bridge" || networkHollow.Name == "host" || networkHollow.Name == "none") {
+ continue
+ }
+
+ // inspect network because the Docker API is a complete mess :)
+ network, err := DockerClient.NetworkInspect(DockerContext, networkHollow.ID, types.NetworkInspectOptions{})
+ if err != nil {
+ utils.Error("NetworkCleanUpInspect", err)
+ continue
+ }
+
+ if(len(network.Containers) > 1) {
+ continue
+ }
+
+ utils.Debug("Ready to Check network: " + network.Name)
+
+ if(config.DockerConfig.SkipPruneNetwork){
+ utils.Debug("Skipping network prune")
+ }
+
+ if(!config.DockerConfig.SkipPruneNetwork && len(network.Containers) == 0) {
+ utils.Log("Removing orphan network: " + network.Name)
+ err := DockerClient.NetworkRemove(DockerContext, network.ID)
+ if err != nil {
+ utils.Error("DockerNetworkCleanupRemove", err)
+ }
+ continue
+ }
+
+ self := os.Getenv("HOSTNAME")
+ if self == "" {
+ utils.Warn("Skipping zombie network cleanup because not a docker cosmos container")
+ continue
+ }
+
+ utils.Debug("Checking self name: " + self)
+ utils.Debug("Checking non-empty network: " + network.Name)
+
+ containsCosmos := false
+ for _, container := range network.Containers {
+ utils.Debug("Checking name: " + container.Name)
+ if(container.Name == self) {
+ containsCosmos = true
+ }
+ }
+
+ if(containsCosmos) {
+ utils.Log("Disconnecting and removing zombie network: " + network.Name)
+ err := DockerClient.NetworkDisconnect(DockerContext, network.ID, self, true)
+ if err != nil {
+ utils.Error("DockerNetworkCleanupDisconnect", err)
+ }
+ err = DockerClient.NetworkRemove(DockerContext, network.ID)
+ if err != nil {
+ utils.Error("DockerNetworkCleanupRemove", err)
+ }
+ }
+ }
+}
diff --git a/src/httpServer.go b/src/httpServer.go
index 8a260b4..252b35a 100644
--- a/src/httpServer.go
+++ b/src/httpServer.go
@@ -10,7 +10,6 @@ import (
"github.com/gorilla/mux"
"strconv"
"time"
- "encoding/json"
"os"
"strings"
"github.com/go-chi/chi/middleware"
@@ -36,13 +35,7 @@ func startHTTPServer(router *mux.Router) {
func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
config := utils.GetMainConfig()
-
-
- // check if Docker overwrite Hostname
- serverHostname := "0.0.0.0" //utils.GetMainConfig().HTTPConfig.Hostname
- // if os.Getenv("HOSTNAME") != "" {
- // serverHostname = os.Getenv("HOSTNAME")
- // }
+ serverHostname := "0.0.0.0"
cfg := simplecert.Default
@@ -147,9 +140,6 @@ func StartServer() {
serverPortHTTP = config.HTTPPort
serverPortHTTPS = config.HTTPSPort
- configJson, _ := json.MarshalIndent(config, "", " ")
- utils.Debug("Configuration" + (string)(configJson))
-
var tlsCert = config.TLSCert
var tlsKey= config.TLSKey
diff --git a/src/utils/types.go b/src/utils/types.go
index 50e2c5a..481c726 100644
--- a/src/utils/types.go
+++ b/src/utils/types.go
@@ -76,6 +76,7 @@ type Config struct {
DisableUserManagement bool
NewInstall bool `validate:"boolean"`
HTTPConfig HTTPConfig `validate:"required,dive,required"`
+ DockerConfig DockerConfig
}
type HTTPConfig struct {
@@ -92,6 +93,10 @@ type HTTPConfig struct {
SSLEmail string `validate:"omitempty,email"`
}
+type DockerConfig struct {
+ SkipPruneNetwork bool
+}
+
type ProxyConfig struct {
Routes []ProxyRouteConfig
}