WIP
- commit
- ad1de4580a0bea1d740786c88e7607bcf19d5a20
- author
- bnema · · 2023-09-06 19:43 UTC
- parent
- 383266c
- signature
- unsigned
4 files · +74 -8
M .env.example +1 -0
| @@ -1,3 +1,4 @@ | |||
| 1 | + | VERSION= VERSION OF THE APP | |
| 1 | 2 | ENV=EITHER PRODUCTION OR DEVELOPMENT | |
| 2 | 3 | LOG_LEVEL= DEBUG, INFO, WARN, ERROR | |
| 3 | 4 | PORT= DEFAULT 1323 | |
| @@ -1,3 +1,4 @@ | |||||
| 1 | + | VERSION= VERSION OF THE APP | |||
| 1 | ENV=EITHER PRODUCTION OR DEVELOPMENT | 2 | ENV=EITHER PRODUCTION OR DEVELOPMENT | ||
| 2 | LOG_LEVEL= DEBUG, INFO, WARN, ERROR | 3 | LOG_LEVEL= DEBUG, INFO, WARN, ERROR | ||
| 3 | PORT= DEFAULT 1323 | 4 | PORT= DEFAULT 1323 | ||
M pkg/docker/commands.go +50 -2
| @@ -1,16 +1,19 @@ | |||
| 1 | 1 | package docker | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | + | "bufio" | |
| 4 | 5 | "context" | |
| 5 | 6 | "fmt" | |
| 6 | 7 | "io" | |
| 7 | 8 | "os" | |
| 9 | + | "os/exec" | |
| 8 | 10 | ||
| 9 | 11 | "github.com/docker/docker/api/types" | |
| 10 | 12 | "github.com/docker/docker/api/types/container" | |
| 11 | 13 | "github.com/docker/docker/client" | |
| 12 | 14 | "github.com/docker/docker/pkg/archive" | |
| 13 | 15 | "github.com/docker/docker/pkg/stdcopy" | |
| 16 | + | "gogs.bnema.dev/gordon-echo/pkg/utils" | |
| 14 | 17 | ) | |
| 15 | 18 | ||
| 16 | 19 | func DockertPullImageTest() { | |
| @@ -144,7 +147,7 @@ func NetworkExists(name string) (bool, error) { | |||
| 144 | 147 | ||
| 145 | 148 | for _, network := range networks { | |
| 146 | 149 | if network.Name == name { | |
| 147 | - | return true | |
| 150 | + | return true, nil | |
| 148 | 151 | } | |
| 149 | 152 | } | |
| 150 | 153 | ||
| @@ -152,7 +155,7 @@ func NetworkExists(name string) (bool, error) { | |||
| 152 | 155 | } | |
| 153 | 156 | ||
| 154 | 157 | // Create network as a bridge | |
| 155 | - | func CreateNetwork(name string) error | |
| 158 | + | func CreateNetwork(name string) error { | |
| 156 | 159 | ctx := context.Background() | |
| 157 | 160 | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) | |
| 158 | 161 | if err != nil { | |
| @@ -167,4 +170,49 @@ func CreateNetwork(name string) error | |||
| 167 | 170 | if err != nil { | |
| 168 | 171 | panic(err) | |
| 169 | 172 | } | |
| 173 | + | ||
| 174 | + | return nil | |
| 175 | + | } | |
| 176 | + | ||
| 177 | + | // CreateContainerFromComposeFile creates containers using docker compose based on the provided compose file. | |
| 178 | + | func CreateContainerFromComposeFile(composeFilePath string, logger *utils.Logger) error { | |
| 179 | + | fmt.Println("Executing CreateContainerFromComposeFile()") | |
| 180 | + | ||
| 181 | + | // Create and start containers using docker compose in the foreground | |
| 182 | + | cmd := exec.Command("docker", "compose", "-f", composeFilePath, "up") | |
| 183 | + | ||
| 184 | + | // Get stdout and stderr pipes | |
| 185 | + | stdout, err := cmd.StdoutPipe() | |
| 186 | + | if err != nil { | |
| 187 | + | return fmt.Errorf("failed to get stdout pipe: %v", err) | |
| 188 | + | } | |
| 189 | + | stderr, err := cmd.StderrPipe() | |
| 190 | + | if err != nil { | |
| 191 | + | return fmt.Errorf("failed to get stderr pipe: %v", err) | |
| 192 | + | } | |
| 193 | + | ||
| 194 | + | // Start the command | |
| 195 | + | if err := cmd.Start(); err != nil { | |
| 196 | + | return fmt.Errorf("failed to start docker compose: %v", err) | |
| 197 | + | } | |
| 198 | + | ||
| 199 | + | // Stream stdout to logger with INFO level | |
| 200 | + | go streamToLogger(stdout, logger, utils.INFO) | |
| 201 | + | // Stream stderr to logger with ERROR level | |
| 202 | + | go streamToLogger(stderr, logger, utils.ERROR) | |
| 203 | + | ||
| 204 | + | // Wait for the command to finish | |
| 205 | + | if err := cmd.Wait(); err != nil { | |
| 206 | + | return fmt.Errorf("docker compose command finished with error: %v", err) | |
| 207 | + | } | |
| 208 | + | ||
| 209 | + | fmt.Println("Containers started successfully using docker compose") | |
| 210 | + | return nil | |
| 211 | + | } | |
| 212 | + | ||
| 213 | + | func streamToLogger(r io.Reader, logger *utils.Logger, level utils.LogLevel) { | |
| 214 | + | scanner := bufio.NewScanner(r) | |
| 215 | + | for scanner.Scan() { | |
| 216 | + | logger.Log(level, scanner.Text()) | |
| 217 | + | } | |
| 170 | 218 | } | |
| @@ -1,16 +1,19 @@ | |||||
| 1 | package docker | 1 | package docker | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | + | "bufio" | |||
| 4 | "context" | 5 | "context" | ||
| 5 | "fmt" | 6 | "fmt" | ||
| 6 | "io" | 7 | "io" | ||
| 7 | "os" | 8 | "os" | ||
| 9 | + | "os/exec" | |||
| 8 | 10 | ||||
| 9 | "github.com/docker/docker/api/types" | 11 | "github.com/docker/docker/api/types" | ||
| 10 | "github.com/docker/docker/api/types/container" | 12 | "github.com/docker/docker/api/types/container" | ||
| 11 | "github.com/docker/docker/client" | 13 | "github.com/docker/docker/client" | ||
| 12 | "github.com/docker/docker/pkg/archive" | 14 | "github.com/docker/docker/pkg/archive" | ||
| 13 | "github.com/docker/docker/pkg/stdcopy" | 15 | "github.com/docker/docker/pkg/stdcopy" | ||
| 16 | + | "gogs.bnema.dev/gordon-echo/pkg/utils" | |||
| 14 | ) | 17 | ) | ||
| 15 | 18 | ||||
| 16 | func DockertPullImageTest() { | 19 | func DockertPullImageTest() { | ||
| @@ -144,7 +147,7 @@ func NetworkExists(name string) (bool, error) { | |||||
| 144 | 147 | ||||
| 145 | for _, network := range networks { | 148 | for _, network := range networks { | ||
| 146 | if network.Name == name { | 149 | if network.Name == name { | ||
| 147 | - | return true | 150 | + | return true, nil |
| 148 | } | 151 | } | ||
| 149 | } | 152 | } | ||
| 150 | 153 | ||||
| @@ -152,7 +155,7 @@ func NetworkExists(name string) (bool, error) { | |||||
| 152 | } | 155 | } | ||
| 153 | 156 | ||||
| 154 | // Create network as a bridge | 157 | // Create network as a bridge | ||
| 155 | - | func CreateNetwork(name string) error | 158 | + | func CreateNetwork(name string) error { |
| 156 | ctx := context.Background() | 159 | ctx := context.Background() | ||
| 157 | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) | 160 | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) | ||
| 158 | if err != nil { | 161 | if err != nil { | ||
| @@ -167,4 +170,49 @@ func CreateNetwork(name string) error | |||||
| 167 | if err != nil { | 170 | if err != nil { | ||
| 168 | panic(err) | 171 | panic(err) | ||
| 169 | } | 172 | } | ||
| 173 | + | ||||
| 174 | + | return nil | |||
| 175 | + | } | |||
| 176 | + | ||||
| 177 | + | // CreateContainerFromComposeFile creates containers using docker compose based on the provided compose file. | |||
| 178 | + | func CreateContainerFromComposeFile(composeFilePath string, logger *utils.Logger) error { | |||
| 179 | + | fmt.Println("Executing CreateContainerFromComposeFile()") | |||
| 180 | + | ||||
| 181 | + | // Create and start containers using docker compose in the foreground | |||
| 182 | + | cmd := exec.Command("docker", "compose", "-f", composeFilePath, "up") | |||
| 183 | + | ||||
| 184 | + | // Get stdout and stderr pipes | |||
| 185 | + | stdout, err := cmd.StdoutPipe() | |||
| 186 | + | if err != nil { | |||
| 187 | + | return fmt.Errorf("failed to get stdout pipe: %v", err) | |||
| 188 | + | } | |||
| 189 | + | stderr, err := cmd.StderrPipe() | |||
| 190 | + | if err != nil { | |||
| 191 | + | return fmt.Errorf("failed to get stderr pipe: %v", err) | |||
| 192 | + | } | |||
| 193 | + | ||||
| 194 | + | // Start the command | |||
| 195 | + | if err := cmd.Start(); err != nil { | |||
| 196 | + | return fmt.Errorf("failed to start docker compose: %v", err) | |||
| 197 | + | } | |||
| 198 | + | ||||
| 199 | + | // Stream stdout to logger with INFO level | |||
| 200 | + | go streamToLogger(stdout, logger, utils.INFO) | |||
| 201 | + | // Stream stderr to logger with ERROR level | |||
| 202 | + | go streamToLogger(stderr, logger, utils.ERROR) | |||
| 203 | + | ||||
| 204 | + | // Wait for the command to finish | |||
| 205 | + | if err := cmd.Wait(); err != nil { | |||
| 206 | + | return fmt.Errorf("docker compose command finished with error: %v", err) | |||
| 207 | + | } | |||
| 208 | + | ||||
| 209 | + | fmt.Println("Containers started successfully using docker compose") | |||
| 210 | + | return nil | |||
| 211 | + | } | |||
| 212 | + | ||||
| 213 | + | func streamToLogger(r io.Reader, logger *utils.Logger, level utils.LogLevel) { | |||
| 214 | + | scanner := bufio.NewScanner(r) | |||
| 215 | + | for scanner.Scan() { | |||
| 216 | + | logger.Log(level, scanner.Text()) | |||
| 217 | + | } | |||
| 170 | } | 218 | } | ||
M pkg/scripts/install-traefik.go +20 -3
| @@ -36,7 +36,6 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 36 | 36 | ||
| 37 | 37 | // Setup the TXT renderer for traefik-compose.goyml | |
| 38 | 38 | rendererCompose, err := templating.GetTXTRenderer("traefik-compose.goyml", modelFS, logger) | |
| 39 | - | fmt.Println("rendererCompose=", rendererCompose) | |
| 40 | 39 | if err != nil { | |
| 41 | 40 | return err | |
| 42 | 41 | } | |
| @@ -45,7 +44,6 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 45 | 44 | composeContent, err := rendererCompose.TXTRender(map[string]string{ | |
| 46 | 45 | "topdomain": topDomain, | |
| 47 | 46 | }) | |
| 48 | - | fmt.Println("composeContent=", composeContent) | |
| 49 | 47 | if err != nil { | |
| 50 | 48 | return err | |
| 51 | 49 | } | |
| @@ -89,7 +87,26 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 89 | 87 | // Ensure that the network "exposed" exists if not create it | |
| 90 | 88 | exists, err := docker.NetworkExists("exposed") | |
| 91 | 89 | if err != nil { | |
| 92 | - | // handle the error | |
| 90 | + | return err | |
| 91 | + | } | |
| 92 | + | if exists { | |
| 93 | + | fmt.Println("Network Exposed found") | |
| 94 | + | } else { | |
| 95 | + | fmt.Println("Network Exposed not found, creating it") | |
| 96 | + | if err := docker.CreateNetwork("exposed"); err != nil { | |
| 97 | + | return err | |
| 98 | + | } | |
| 99 | + | } | |
| 100 | + | ||
| 101 | + | fmt.Println("Network created successfully") | |
| 102 | + | ||
| 103 | + | // Create the containers with CreateContainerFromComposeFile | |
| 104 | + | if err := docker.CreateContainerFromComposeFile(path+"traefik/docker-compose.yml", logger); err != nil { | |
| 105 | + | return err | |
| 93 | 106 | } | |
| 94 | 107 | ||
| 108 | + | fmt.Println("Containers created successfully") | |
| 109 | + | ||
| 110 | + | return nil | |
| 111 | + | ||
| 95 | 112 | } | |
| @@ -36,7 +36,6 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 36 | 36 | ||||
| 37 | // Setup the TXT renderer for traefik-compose.goyml | 37 | // Setup the TXT renderer for traefik-compose.goyml | ||
| 38 | rendererCompose, err := templating.GetTXTRenderer("traefik-compose.goyml", modelFS, logger) | 38 | rendererCompose, err := templating.GetTXTRenderer("traefik-compose.goyml", modelFS, logger) | ||
| 39 | - | fmt.Println("rendererCompose=", rendererCompose) | |||
| 40 | if err != nil { | 39 | if err != nil { | ||
| 41 | return err | 40 | return err | ||
| 42 | } | 41 | } | ||
| @@ -45,7 +44,6 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 45 | composeContent, err := rendererCompose.TXTRender(map[string]string{ | 44 | composeContent, err := rendererCompose.TXTRender(map[string]string{ | ||
| 46 | "topdomain": topDomain, | 45 | "topdomain": topDomain, | ||
| 47 | }) | 46 | }) | ||
| 48 | - | fmt.Println("composeContent=", composeContent) | |||
| 49 | if err != nil { | 47 | if err != nil { | ||
| 50 | return err | 48 | return err | ||
| 51 | } | 49 | } | ||
| @@ -89,7 +87,26 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 89 | // Ensure that the network "exposed" exists if not create it | 87 | // Ensure that the network "exposed" exists if not create it | ||
| 90 | exists, err := docker.NetworkExists("exposed") | 88 | exists, err := docker.NetworkExists("exposed") | ||
| 91 | if err != nil { | 89 | if err != nil { | ||
| 92 | - | // handle the error | 90 | + | return err |
| 91 | + | } | |||
| 92 | + | if exists { | |||
| 93 | + | fmt.Println("Network Exposed found") | |||
| 94 | + | } else { | |||
| 95 | + | fmt.Println("Network Exposed not found, creating it") | |||
| 96 | + | if err := docker.CreateNetwork("exposed"); err != nil { | |||
| 97 | + | return err | |||
| 98 | + | } | |||
| 99 | + | } | |||
| 100 | + | ||||
| 101 | + | fmt.Println("Network created successfully") | |||
| 102 | + | ||||
| 103 | + | // Create the containers with CreateContainerFromComposeFile | |||
| 104 | + | if err := docker.CreateContainerFromComposeFile(path+"traefik/docker-compose.yml", logger); err != nil { | |||
| 105 | + | return err | |||
| 93 | } | 106 | } | ||
| 94 | 107 | ||||
| 108 | + | fmt.Println("Containers created successfully") | |||
| 109 | + | ||||
| 110 | + | return nil | |||
| 111 | + | ||||
| 95 | } | 112 | } | ||
M pkg/templating/models/traefik-compose.goyml +3 -3
| @@ -10,9 +10,9 @@ services: | |||
| 10 | 10 | - "443:443" | |
| 11 | 11 | volumes: | |
| 12 | 12 | - /var/run/docker.sock:/var/run/docker.sock:ro | |
| 13 | - | - traefik.yml:/etc/traefik/traefik.yml | |
| 14 | - | - traefik/volume/acme.json:/acme.json | |
| 15 | - | - traefik/volume/traefik.log:/var/log/traefik/traefik.log | |
| 13 | + | - ./traefik.yml:/etc/traefik/traefik.yml | |
| 14 | + | - ./traefik/volume/acme.json:/acme.json | |
| 15 | + | - ./traefik.log:/var/log/traefik/traefik.log | |
| 16 | 16 | labels: | |
| 17 | 17 | - "traefik.enable=true" | |
| 18 | 18 | - "traefik.http.routers.api.rule=Host(`traefik.{{ .topdomain }}`)" | |
| @@ -10,9 +10,9 @@ services: | |||||
| 10 | - "443:443" | 10 | - "443:443" | ||
| 11 | volumes: | 11 | volumes: | ||
| 12 | - /var/run/docker.sock:/var/run/docker.sock:ro | 12 | - /var/run/docker.sock:/var/run/docker.sock:ro | ||
| 13 | - | - traefik.yml:/etc/traefik/traefik.yml | 13 | + | - ./traefik.yml:/etc/traefik/traefik.yml |
| 14 | - | - traefik/volume/acme.json:/acme.json | 14 | + | - ./traefik/volume/acme.json:/acme.json |
| 15 | - | - traefik/volume/traefik.log:/var/log/traefik/traefik.log | 15 | + | - ./traefik.log:/var/log/traefik/traefik.log |
| 16 | labels: | 16 | labels: | ||
| 17 | - "traefik.enable=true" | 17 | - "traefik.enable=true" | ||
| 18 | - "traefik.http.routers.api.rule=Host(`traefik.{{ .topdomain }}`)" | 18 | - "traefik.http.routers.api.rule=Host(`traefik.{{ .topdomain }}`)" | ||