Volumes and Env inputs can be empty
- commit
- c46ba10e1afa157e0a15993f6ae3f9b549f6ff5f
- author
- bnema · · 2023-10-20 14:12 UTC
- parent
- 96ba59c
- signature
- unsigned
4 files · +48 -15
M internal/templating/render/cmdparams.go +10 -0
| @@ -13,10 +13,20 @@ func FromInputsToCmdParams(inputs map[string]string, a *app.App) (docker.Contain | |||
| 13 | 13 | volumeStr := inputs["volumes"] | |
| 14 | 14 | volumeSlice := strings.Split(volumeStr, ",") | |
| 15 | 15 | ||
| 16 | + | // If there is no volume value we just resturn an empty strings "" | |
| 17 | + | if len(volumeSlice) == 1 && volumeSlice[0] == "" { | |
| 18 | + | volumeSlice = []string{} | |
| 19 | + | } | |
| 20 | + | ||
| 16 | 21 | // Retreive the content of the textarea environment_variables and create a slice of strings | |
| 17 | 22 | environmentStr := inputs["environment_variables"] | |
| 18 | 23 | environmentSlice := strings.Split(environmentStr, "\n") | |
| 19 | 24 | ||
| 25 | + | // If there is no environment value we just resturn an empty strings "" | |
| 26 | + | if len(environmentSlice) == 1 && environmentSlice[0] == "" { | |
| 27 | + | environmentSlice = []string{} | |
| 28 | + | } | |
| 29 | + | ||
| 20 | 30 | // Ports input parsing | |
| 21 | 31 | portMappingsStr := inputs["ports"] | |
| 22 | 32 | portMappingsSliceRaw := strings.Split(portMappingsStr, ",") | |
| @@ -13,10 +13,20 @@ func FromInputsToCmdParams(inputs map[string]string, a *app.App) (docker.Contain | |||||
| 13 | volumeStr := inputs["volumes"] | 13 | volumeStr := inputs["volumes"] | ||
| 14 | volumeSlice := strings.Split(volumeStr, ",") | 14 | volumeSlice := strings.Split(volumeStr, ",") | ||
| 15 | 15 | ||||
| 16 | + | // If there is no volume value we just resturn an empty strings "" | |||
| 17 | + | if len(volumeSlice) == 1 && volumeSlice[0] == "" { | |||
| 18 | + | volumeSlice = []string{} | |||
| 19 | + | } | |||
| 20 | + | ||||
| 16 | // Retreive the content of the textarea environment_variables and create a slice of strings | 21 | // Retreive the content of the textarea environment_variables and create a slice of strings | ||
| 17 | environmentStr := inputs["environment_variables"] | 22 | environmentStr := inputs["environment_variables"] | ||
| 18 | environmentSlice := strings.Split(environmentStr, "\n") | 23 | environmentSlice := strings.Split(environmentStr, "\n") | ||
| 19 | 24 | ||||
| 25 | + | // If there is no environment value we just resturn an empty strings "" | |||
| 26 | + | if len(environmentSlice) == 1 && environmentSlice[0] == "" { | |||
| 27 | + | environmentSlice = []string{} | |||
| 28 | + | } | |||
| 29 | + | ||||
| 20 | // Ports input parsing | 30 | // Ports input parsing | ||
| 21 | portMappingsStr := inputs["ports"] | 31 | portMappingsStr := inputs["ports"] | ||
| 22 | portMappingsSliceRaw := strings.Split(portMappingsStr, ",") | 32 | portMappingsSliceRaw := strings.Split(portMappingsStr, ",") | ||
M pkg/docker/client.go +29 -9
| @@ -3,9 +3,10 @@ package docker | |||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | 5 | "fmt" | |
| 6 | - | "log" | |
| 7 | 6 | "os" | |
| 7 | + | "time" | |
| 8 | 8 | ||
| 9 | + | "github.com/docker/docker/api/types" | |
| 9 | 10 | "github.com/docker/docker/client" | |
| 10 | 11 | ) | |
| 11 | 12 | ||
| @@ -18,7 +19,10 @@ type Config struct { | |||
| 18 | 19 | PodmanEnable bool | |
| 19 | 20 | } | |
| 20 | 21 | ||
| 21 | - | var dockerCli *client.Client | |
| 22 | + | var ( | |
| 23 | + | dockerCli *client.Client | |
| 24 | + | currentConfig *Config | |
| 25 | + | ) | |
| 22 | 26 | ||
| 23 | 27 | // DockerClient implements the ContainerEngineClient interface for Docker | |
| 24 | 28 | type DockerClient struct{} | |
| @@ -31,30 +35,46 @@ func (d *DockerClient) InitializeClient(config *Config) error { | |||
| 31 | 35 | ||
| 32 | 36 | // Check if the socket file exists if not return an error | |
| 33 | 37 | if _, err := os.Stat(config.Sock); os.IsNotExist(err) { | |
| 34 | - | return fmt.Errorf("Sock file does not exist: %s", config.Sock) | |
| 38 | + | return err | |
| 35 | 39 | } | |
| 36 | 40 | ||
| 37 | 41 | // Initialize Docker client | |
| 38 | 42 | cli, err := client.NewClientWithOpts( | |
| 39 | 43 | client.WithAPIVersionNegotiation(), | |
| 40 | - | client.WithHost("unix://"+config.Sock), // Prepend "unix://" to the Unix socket path | |
| 44 | + | client.WithHost("unix://"+config.Sock), | |
| 41 | 45 | ) | |
| 42 | 46 | if err != nil { | |
| 43 | - | log.Printf("Error initializing Docker client: %s", err) | |
| 44 | - | return err | |
| 47 | + | return fmt.Errorf("Error initializing Docker client: %s", err) | |
| 45 | 48 | } | |
| 46 | 49 | dockerCli = cli | |
| 50 | + | currentConfig = config | |
| 47 | 51 | return nil | |
| 48 | 52 | } | |
| 49 | 53 | ||
| 54 | + | // CheckIfInitialized checks if the Docker client is initialized | |
| 50 | 55 | func CheckIfInitialized() error { | |
| 56 | + | // Check if there is a socket file | |
| 57 | + | if currentConfig == nil || currentConfig.Sock == "" { | |
| 58 | + | return fmt.Errorf("Docker client is not initialized or configuration is missing") | |
| 59 | + | } | |
| 60 | + | ||
| 61 | + | socketPath := currentConfig.Sock // Use the package-level variable | |
| 62 | + | if _, err := os.Stat(socketPath); os.IsNotExist(err) { | |
| 63 | + | return fmt.Errorf("Sock file does not exist: %s", socketPath) | |
| 64 | + | } | |
| 65 | + | ||
| 66 | + | // Then we check if the dockerCli is nil | |
| 51 | 67 | if dockerCli == nil { | |
| 52 | 68 | return fmt.Errorf("Docker client is not initialized") | |
| 53 | 69 | } | |
| 54 | - | // ping the Docker daemon to check if it's running | |
| 55 | - | _, err := dockerCli.Ping(context.Background()) | |
| 70 | + | ||
| 71 | + | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | |
| 72 | + | defer cancel() | |
| 73 | + | ||
| 74 | + | // More stringent check: try to list containers | |
| 75 | + | _, err := dockerCli.ContainerList(ctx, types.ContainerListOptions{}) | |
| 56 | 76 | if err != nil { | |
| 57 | - | return fmt.Errorf("Docker client is not initialized") | |
| 77 | + | return fmt.Errorf("Cannot connect to Docker daemon: %s", err) | |
| 58 | 78 | } | |
| 59 | 79 | return nil | |
| 60 | 80 | } | |
| @@ -3,9 +3,10 @@ package docker | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | - | "log" | |||
| 7 | "os" | 6 | "os" | ||
| 7 | + | "time" | |||
| 8 | 8 | ||||
| 9 | + | "github.com/docker/docker/api/types" | |||
| 9 | "github.com/docker/docker/client" | 10 | "github.com/docker/docker/client" | ||
| 10 | ) | 11 | ) | ||
| 11 | 12 | ||||
| @@ -18,7 +19,10 @@ type Config struct { | |||||
| 18 | PodmanEnable bool | 19 | PodmanEnable bool | ||
| 19 | } | 20 | } | ||
| 20 | 21 | ||||
| 21 | - | var dockerCli *client.Client | 22 | + | var ( |
| 23 | + | dockerCli *client.Client | |||
| 24 | + | currentConfig *Config | |||
| 25 | + | ) | |||
| 22 | 26 | ||||
| 23 | // DockerClient implements the ContainerEngineClient interface for Docker | 27 | // DockerClient implements the ContainerEngineClient interface for Docker | ||
| 24 | type DockerClient struct{} | 28 | type DockerClient struct{} | ||
| @@ -31,30 +35,46 @@ func (d *DockerClient) InitializeClient(config *Config) error { | |||||
| 31 | 35 | ||||
| 32 | // Check if the socket file exists if not return an error | 36 | // Check if the socket file exists if not return an error | ||
| 33 | if _, err := os.Stat(config.Sock); os.IsNotExist(err) { | 37 | if _, err := os.Stat(config.Sock); os.IsNotExist(err) { | ||
| 34 | - | return fmt.Errorf("Sock file does not exist: %s", config.Sock) | 38 | + | return err |
| 35 | } | 39 | } | ||
| 36 | 40 | ||||
| 37 | // Initialize Docker client | 41 | // Initialize Docker client | ||
| 38 | cli, err := client.NewClientWithOpts( | 42 | cli, err := client.NewClientWithOpts( | ||
| 39 | client.WithAPIVersionNegotiation(), | 43 | client.WithAPIVersionNegotiation(), | ||
| 40 | - | client.WithHost("unix://"+config.Sock), // Prepend "unix://" to the Unix socket path | 44 | + | client.WithHost("unix://"+config.Sock), |
| 41 | ) | 45 | ) | ||
| 42 | if err != nil { | 46 | if err != nil { | ||
| 43 | - | log.Printf("Error initializing Docker client: %s", err) | 47 | + | return fmt.Errorf("Error initializing Docker client: %s", err) |
| 44 | - | return err | |||
| 45 | } | 48 | } | ||
| 46 | dockerCli = cli | 49 | dockerCli = cli | ||
| 50 | + | currentConfig = config | |||
| 47 | return nil | 51 | return nil | ||
| 48 | } | 52 | } | ||
| 49 | 53 | ||||
| 54 | + | // CheckIfInitialized checks if the Docker client is initialized | |||
| 50 | func CheckIfInitialized() error { | 55 | func CheckIfInitialized() error { | ||
| 56 | + | // Check if there is a socket file | |||
| 57 | + | if currentConfig == nil || currentConfig.Sock == "" { | |||
| 58 | + | return fmt.Errorf("Docker client is not initialized or configuration is missing") | |||
| 59 | + | } | |||
| 60 | + | ||||
| 61 | + | socketPath := currentConfig.Sock // Use the package-level variable | |||
| 62 | + | if _, err := os.Stat(socketPath); os.IsNotExist(err) { | |||
| 63 | + | return fmt.Errorf("Sock file does not exist: %s", socketPath) | |||
| 64 | + | } | |||
| 65 | + | ||||
| 66 | + | // Then we check if the dockerCli is nil | |||
| 51 | if dockerCli == nil { | 67 | if dockerCli == nil { | ||
| 52 | return fmt.Errorf("Docker client is not initialized") | 68 | return fmt.Errorf("Docker client is not initialized") | ||
| 53 | } | 69 | } | ||
| 54 | - | // ping the Docker daemon to check if it's running | 70 | + | |
| 55 | - | _, err := dockerCli.Ping(context.Background()) | 71 | + | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 72 | + | defer cancel() | |||
| 73 | + | ||||
| 74 | + | // More stringent check: try to list containers | |||
| 75 | + | _, err := dockerCli.ContainerList(ctx, types.ContainerListOptions{}) | |||
| 56 | if err != nil { | 76 | if err != nil { | ||
| 57 | - | return fmt.Errorf("Docker client is not initialized") | 77 | + | return fmt.Errorf("Cannot connect to Docker daemon: %s", err) |
| 58 | } | 78 | } | ||
| 59 | return nil | 79 | return nil | ||
| 60 | } | 80 | } | ||
M pkg/docker/containers.go +8 -5
| @@ -88,12 +88,19 @@ func ContainerCommandParamsToConfig(cmdParams ContainerCommandParams) (*containe | |||
| 88 | 88 | // ListRunningContainers lists all running containers | |
| 89 | 89 | func ListRunningContainers() ([]types.Container, error) { | |
| 90 | 90 | // Check if the Docker client has been initialized | |
| 91 | - | CheckIfInitialized() | |
| 91 | + | err := CheckIfInitialized() | |
| 92 | + | if err != nil { | |
| 93 | + | return nil, err | |
| 94 | + | } | |
| 92 | 95 | // List containers using the Docker client: | |
| 93 | 96 | containers, err := dockerCli.ContainerList(context.Background(), types.ContainerListOptions{All: true}) | |
| 94 | 97 | if err != nil { | |
| 95 | 98 | return nil, err | |
| 96 | 99 | } | |
| 100 | + | // Check if the list is empty | |
| 101 | + | if len(containers) == 0 { | |
| 102 | + | return nil, fmt.Errorf("No containers found") | |
| 103 | + | } | |
| 97 | 104 | return containers, nil | |
| 98 | 105 | } | |
| 99 | 106 | ||
| @@ -106,7 +113,6 @@ func StopContainer(containerID string) error { | |||
| 106 | 113 | ||
| 107 | 114 | // StopContainerGracefully stops a container by sending a SIGTERM and waiting for it to stop | |
| 108 | 115 | func StopContainerGracefully(containerID string, timeoutDuration time.Duration) (bool, error) { | |
| 109 | - | ||
| 110 | 116 | // Start by sending a SIGTERM | |
| 111 | 117 | err := dockerCli.ContainerKill(context.Background(), containerID, "SIGTERM") | |
| 112 | 118 | if err != nil { | |
| @@ -253,7 +259,6 @@ func CreateContainer(cmdParams ContainerCommandParams) (string, error) { | |||
| 253 | 259 | ||
| 254 | 260 | // GetContainerInfo returns information about a container | |
| 255 | 261 | func GetContainerInfo(containerID string) (types.ContainerJSON, error) { | |
| 256 | - | ||
| 257 | 262 | // Get container info using the Docker client | |
| 258 | 263 | containerInfo, err := dockerCli.ContainerInspect(context.Background(), containerID) | |
| 259 | 264 | if err != nil { | |
| @@ -300,7 +305,6 @@ func UpdateContainerConfig(containerID string, newConfig *container.Config, newH | |||
| 300 | 305 | ||
| 301 | 306 | // GetContainerLogs returns the logs of a container | |
| 302 | 307 | func GetContainerLogs(containerID string) (string, error) { | |
| 303 | - | ||
| 304 | 308 | // Get container logs using the Docker client | |
| 305 | 309 | containerLogs, err := dockerCli.ContainerLogs(context.Background(), containerID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) | |
| 306 | 310 | if err != nil { | |
| @@ -317,7 +321,6 @@ func GetContainerLogs(containerID string) (string, error) { | |||
| 317 | 321 | ||
| 318 | 322 | // CheckContainerStatus checks if a container with the given name exists and is running | |
| 319 | 323 | func CheckContainerStatus(containerName string) (bool, bool, error) { | |
| 320 | - | ||
| 321 | 324 | // List all containers | |
| 322 | 325 | containers, err := ListRunningContainers() | |
| 323 | 326 | if err != nil { | |
| @@ -88,12 +88,19 @@ func ContainerCommandParamsToConfig(cmdParams ContainerCommandParams) (*containe | |||||
| 88 | // ListRunningContainers lists all running containers | 88 | // ListRunningContainers lists all running containers | ||
| 89 | func ListRunningContainers() ([]types.Container, error) { | 89 | func ListRunningContainers() ([]types.Container, error) { | ||
| 90 | // Check if the Docker client has been initialized | 90 | // Check if the Docker client has been initialized | ||
| 91 | - | CheckIfInitialized() | 91 | + | err := CheckIfInitialized() |
| 92 | + | if err != nil { | |||
| 93 | + | return nil, err | |||
| 94 | + | } | |||
| 92 | // List containers using the Docker client: | 95 | // List containers using the Docker client: | ||
| 93 | containers, err := dockerCli.ContainerList(context.Background(), types.ContainerListOptions{All: true}) | 96 | containers, err := dockerCli.ContainerList(context.Background(), types.ContainerListOptions{All: true}) | ||
| 94 | if err != nil { | 97 | if err != nil { | ||
| 95 | return nil, err | 98 | return nil, err | ||
| 96 | } | 99 | } | ||
| 100 | + | // Check if the list is empty | |||
| 101 | + | if len(containers) == 0 { | |||
| 102 | + | return nil, fmt.Errorf("No containers found") | |||
| 103 | + | } | |||
| 97 | return containers, nil | 104 | return containers, nil | ||
| 98 | } | 105 | } | ||
| 99 | 106 | ||||
| @@ -106,7 +113,6 @@ func StopContainer(containerID string) error { | |||||
| 106 | 113 | ||||
| 107 | // StopContainerGracefully stops a container by sending a SIGTERM and waiting for it to stop | 114 | // StopContainerGracefully stops a container by sending a SIGTERM and waiting for it to stop | ||
| 108 | func StopContainerGracefully(containerID string, timeoutDuration time.Duration) (bool, error) { | 115 | func StopContainerGracefully(containerID string, timeoutDuration time.Duration) (bool, error) { | ||
| 109 | - | ||||
| 110 | // Start by sending a SIGTERM | 116 | // Start by sending a SIGTERM | ||
| 111 | err := dockerCli.ContainerKill(context.Background(), containerID, "SIGTERM") | 117 | err := dockerCli.ContainerKill(context.Background(), containerID, "SIGTERM") | ||
| 112 | if err != nil { | 118 | if err != nil { | ||
| @@ -253,7 +259,6 @@ func CreateContainer(cmdParams ContainerCommandParams) (string, error) { | |||||
| 253 | 259 | ||||
| 254 | // GetContainerInfo returns information about a container | 260 | // GetContainerInfo returns information about a container | ||
| 255 | func GetContainerInfo(containerID string) (types.ContainerJSON, error) { | 261 | func GetContainerInfo(containerID string) (types.ContainerJSON, error) { | ||
| 256 | - | ||||
| 257 | // Get container info using the Docker client | 262 | // Get container info using the Docker client | ||
| 258 | containerInfo, err := dockerCli.ContainerInspect(context.Background(), containerID) | 263 | containerInfo, err := dockerCli.ContainerInspect(context.Background(), containerID) | ||
| 259 | if err != nil { | 264 | if err != nil { | ||
| @@ -300,7 +305,6 @@ func UpdateContainerConfig(containerID string, newConfig *container.Config, newH | |||||
| 300 | 305 | ||||
| 301 | // GetContainerLogs returns the logs of a container | 306 | // GetContainerLogs returns the logs of a container | ||
| 302 | func GetContainerLogs(containerID string) (string, error) { | 307 | func GetContainerLogs(containerID string) (string, error) { | ||
| 303 | - | ||||
| 304 | // Get container logs using the Docker client | 308 | // Get container logs using the Docker client | ||
| 305 | containerLogs, err := dockerCli.ContainerLogs(context.Background(), containerID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) | 309 | containerLogs, err := dockerCli.ContainerLogs(context.Background(), containerID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) | ||
| 306 | if err != nil { | 310 | if err != nil { | ||
| @@ -317,7 +321,6 @@ func GetContainerLogs(containerID string) (string, error) { | |||||
| 317 | 321 | ||||
| 318 | // CheckContainerStatus checks if a container with the given name exists and is running | 322 | // CheckContainerStatus checks if a container with the given name exists and is running | ||
| 319 | func CheckContainerStatus(containerName string) (bool, bool, error) { | 323 | func CheckContainerStatus(containerName string) (bool, bool, error) { | ||
| 320 | - | ||||
| 321 | // List all containers | 324 | // List all containers | ||
| 322 | containers, err := ListRunningContainers() | 325 | containers, err := ListRunningContainers() | ||
| 323 | if err != nil { | 326 | if err != nil { | ||
M pkg/htmx/htmlfragments.go +1 -1
| @@ -6,7 +6,7 @@ import ( | |||
| 6 | 6 | ||
| 7 | 7 | "github.com/PuerkitoBio/goquery" | |
| 8 | 8 | "github.com/bnema/gordon/internal/app" | |
| 9 | - | "github.com/bnema/gordon/internal/templates/render" | |
| 9 | + | "github.com/bnema/gordon/internal/templating/render" | |
| 10 | 10 | ) | |
| 11 | 11 | ||
| 12 | 12 | // GetHTMLFragmentByID returns the HTML fragment with the specified id | |
| @@ -6,7 +6,7 @@ import ( | |||||
| 6 | 6 | ||||
| 7 | "github.com/PuerkitoBio/goquery" | 7 | "github.com/PuerkitoBio/goquery" | ||
| 8 | "github.com/bnema/gordon/internal/app" | 8 | "github.com/bnema/gordon/internal/app" | ||
| 9 | - | "github.com/bnema/gordon/internal/templates/render" | 9 | + | "github.com/bnema/gordon/internal/templating/render" |
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
| 12 | // GetHTMLFragmentByID returns the HTML fragment with the specified id | 12 | // GetHTMLFragmentByID returns the HTML fragment with the specified id | ||