@@ -2,6 +2,8 @@ package main
22
33import (
44 _ "embed"
5+ "bytes"
6+ "encoding/json"
57 "errors"
68 "fmt"
79 "github.com/charmbracelet/huh"
@@ -10,40 +12,38 @@ import (
1012 "os/exec"
1113 "path/filepath"
1214 "slices"
13- "strings"
1415 "strconv"
16+ "strings"
1517)
1618
1719var defaultContainerBasePath = "/var/container:/srv/container"
1820var defaultContainerExecCommand = "docker compose -f %COMPOSE exec --user root %SERVICE /bin/sh"
21+ var defaultContainerExecCommandNotRunning = "docker compose -f %COMPOSE exec --user root %SERVICE /bin/sh"
1922var defaultMaxDepth = 2
2023
2124//go:embed HELP.md
2225var help string
2326
2427var version = "development"
2528
26- func isDirectory (path string ) (bool , error ) {
29+ func isDirectory (path string ) (bool ) {
2730 info , err := os .Stat (path )
2831 if err != nil {
29- return false , err
32+ return false
3033 }
31- return info .IsDir (), nil
34+ return info .IsDir ()
3235}
3336
3437func getComposeFilesInDir (basePath string , maxDepth int ) ([]string , error ) {
35- isDir , err := isDirectory (basePath )
36- if err != nil {
37- return nil , err
38- }
38+ isDir := isDirectory (basePath )
3939 if ! isDir {
4040 return nil , fmt .Errorf ("%s is not a directory" , basePath )
4141 }
4242
4343 composeFileNames := []string {"docker-compose.yml" , "docker-compose.yaml" , "compose.yml" , "compose.yaml" }
4444 var composeFiles []string
4545
46- err = filepath .Walk (basePath , func (path string , info os.FileInfo , err error ) error {
46+ err : = filepath .Walk (basePath , func (path string , info os.FileInfo , err error ) error {
4747 if err != nil {
4848 return err
4949 }
@@ -150,12 +150,42 @@ func getDockerServiceArray(dockerComposeYaml string) ([]string, error) {
150150 return serviceKeys , nil
151151}
152152
153+ func isDockerRunning (dockerComposeYaml string , dockerService string ) bool {
154+ cmd := exec .Command ("docker" , fmt .Sprintf ("compose -f %s ps %s --format json" , dockerComposeYaml , dockerService ))
155+
156+ var out bytes.Buffer
157+ cmd .Stdout = & out
158+ err := cmd .Run ()
159+ if err != nil {
160+ return false
161+ }
162+
163+ var jsonData map [string ]interface {}
164+ err = json .Unmarshal (out .Bytes (), & jsonData )
165+ if err != nil {
166+ return false
167+ }
168+ if len (jsonData ) == 0 {
169+ return false
170+ }
171+ if jsonData ["State" ] == "running" {
172+ return true
173+ }
174+
175+ return false
176+ }
177+
153178func runDockerExec (dockerComposeYaml string , dockerService string ) error {
154179 dockerExecCommand := os .Getenv ("CONTAINER_EXEC_COMMAND" )
155180 if dockerExecCommand == "" {
156181 dockerExecCommand = defaultContainerExecCommand
157182 }
158183
184+ dockerExecCommandNotRunningExec := os .Getenv ("CONTAINER_EXEC_COMMAND_NOT_RUNNING" )
185+ if dockerExecCommandNotRunningExec == "" {
186+ dockerExecCommandNotRunningExec = defaultContainerExecCommandNotRunning
187+ }
188+
159189 dockerExecCommandParts := strings .Split (dockerExecCommand , " " )
160190 for i , part := range dockerExecCommandParts {
161191 switch part {
@@ -166,10 +196,27 @@ func runDockerExec(dockerComposeYaml string, dockerService string) error {
166196 }
167197 }
168198
169- fmt .Printf ("dockerExecCommand: %s\n " , dockerExecCommand )
170- fmt .Printf ("runDockerCommand: %s\n " , strings .Join (dockerExecCommandParts , " " ))
199+ dockerExecCommandNotRunningExecParts := strings .Split (dockerExecCommandNotRunningExec , " " )
200+ for i , part := range dockerExecCommandNotRunningExecParts {
201+ switch part {
202+ case "%COMPOSE" :
203+ dockerExecCommandNotRunningExecParts [i ] = dockerComposeYaml
204+ case "%SERVICE" :
205+ dockerExecCommandNotRunningExecParts [i ] = dockerService
206+ }
207+ }
208+
209+ var cmd * exec.Cmd
210+ if isDockerRunning (dockerComposeYaml , dockerService ) {
211+ fmt .Printf ("Docker container %s %s is running\n " , dockerComposeYaml , dockerService )
212+ fmt .Printf ("exec: %s\n " , strings .Join (dockerExecCommandParts , " " ))
213+ cmd = exec .Command (dockerExecCommandParts [0 ], dockerExecCommandParts [1 :]... )
214+ } else {
215+ fmt .Printf ("Docker container %s %s is NOT running\n " , dockerComposeYaml , dockerService )
216+ fmt .Printf ("exec: %s\n " , strings .Join (dockerExecCommandNotRunningExecParts , " " ))
217+ cmd = exec .Command (dockerExecCommandNotRunningExecParts [0 ], dockerExecCommandNotRunningExecParts [1 :]... )
218+ }
171219
172- cmd := exec .Command (dockerExecCommandParts [0 ], dockerExecCommandParts [1 :]... )
173220 cmd .Stdin = os .Stdin
174221 cmd .Stdout = os .Stdout
175222 cmd .Stderr = os .Stderr
@@ -201,7 +248,7 @@ func main() {
201248 os .Exit (1 )
202249 }
203250 if len (allComposeFiles ) == 0 {
204- fmt .Printf ("Error: no docker compose YAML found in %s\n " , paths )
251+ fmt .Printf ("No docker compose YAML found in %s\n " , paths )
205252 os .Exit (1 )
206253 }
207254
0 commit comments