Skip to content

Commit e7623ee

Browse files
committed
This commit resolves #221, to specify stacks that are currently on your local machine running.
Signed-off-by: tobigiwa <[email protected]>
1 parent 27d445b commit e7623ee

File tree

3 files changed

+113
-5
lines changed

3 files changed

+113
-5
lines changed

cmd/ps.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright © 2023 Giwa Oluwatobi <[email protected]>
3+
*/
4+
package cmd
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
11+
"github.com/hyperledger/firefly-cli/internal/log"
12+
"github.com/hyperledger/firefly-cli/internal/stacks"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
// psCmd represents the ps command
17+
var psCmd = &cobra.Command{
18+
Use: "ps [a stack name]...",
19+
Short: "Returns information on running stacks",
20+
Long: `ps returns currently running stacks on your local machine.
21+
22+
It also takes a continuous list of whitespace optional arguement - stack name.`,
23+
Aliases: []string{"process"},
24+
RunE: func(cmd *cobra.Command, args []string) error {
25+
26+
ctx := log.WithVerbosity(context.Background(), verbose)
27+
ctx = log.WithLogger(ctx, logger)
28+
29+
allStacks, err := stacks.ListStacks()
30+
if err != nil {
31+
return err
32+
}
33+
34+
if len(args) > 0 {
35+
namedStacks := make([]string, 0, len(args))
36+
for _, stackName := range args {
37+
if contains(allStacks, strings.TrimSpace(stackName)) {
38+
namedStacks = append(namedStacks, stackName)
39+
} else {
40+
fmt.Printf("stack name - %s, is not present on your local machine. Run `ff ls` to see all available stacks.\n", stackName)
41+
}
42+
}
43+
44+
allStacks = namedStacks // replace only the user specified stacks in the slice instead.
45+
}
46+
47+
stackManager := stacks.NewStackManager(ctx)
48+
for _, stackName := range allStacks {
49+
if err := stackManager.LoadStack(stackName); err != nil {
50+
return err
51+
}
52+
53+
if err := stackManager.IsRunning(); err != nil {
54+
return err
55+
}
56+
}
57+
return nil
58+
},
59+
}
60+
61+
func init() {
62+
rootCmd.AddCommand(psCmd)
63+
}
64+
65+
// contains can be removed if the go mod version is bumped to version Go 1.18
66+
// and replaced with slices.Contains().
67+
func contains(s []string, str string) bool {
68+
for _, v := range s {
69+
if v == str {
70+
return true
71+
}
72+
}
73+
return false
74+
}

internal/docker/docker.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ func RunDockerCommandBuffered(ctx context.Context, workingDir string, command ..
111111
return runCommand(ctx, dockerCmd)
112112
}
113113

114+
func RunDockerComposeCommandReturnsStdout(workingDir string, command ...string) ([]byte, error) {
115+
dockerCmd := exec.Command("docker", append([]string{"compose"}, command...)...)
116+
dockerCmd.Dir = workingDir
117+
return dockerCmd.Output()
118+
}
119+
114120
func runCommand(ctx context.Context, cmd *exec.Cmd) (string, error) {
115121
verbose := log.VerbosityFromContext(ctx)
116122
isLogCmd, _ := ctx.Value(CtxIsLogCmdKey{}).(bool)

internal/stacks/stack_manager.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import (
2727
"path"
2828
"path/filepath"
2929
"strings"
30+
"sync"
3031
"syscall"
32+
"text/tabwriter"
3133
"time"
3234

3335
"github.com/hyperledger/firefly-cli/internal/blockchain"
@@ -58,21 +60,20 @@ type StackManager struct {
5860
blockchainProvider blockchain.IBlockchainProvider
5961
tokenProviders []tokens.ITokensProvider
6062
IsOldFileStructure bool
63+
once sync.Once
6164
}
6265

6366
func ListStacks() ([]string, error) {
64-
files, err := ioutil.ReadDir(constants.StacksDir)
67+
files, err := os.ReadDir(constants.StacksDir)
6568
if err != nil {
6669
return nil, err
6770
}
6871

69-
stacks := make([]string, 0)
70-
i := 0
72+
stacks := make([]string, 0, len(files))
7173
for _, f := range files {
7274
if f.IsDir() {
7375
if exists, err := CheckExists(f.Name()); err == nil && exists {
7476
stacks = append(stacks, f.Name())
75-
i++
7677
}
7778
}
7879
}
@@ -250,7 +251,7 @@ func (s *StackManager) LoadStack(stackName string) error {
250251
if !exists {
251252
return fmt.Errorf("stack '%s' does not exist", stackName)
252253
}
253-
d, err := ioutil.ReadFile(filepath.Join(stackDir, "stack.json"))
254+
d, err := os.ReadFile(filepath.Join(stackDir, "stack.json"))
254255
if err != nil {
255256
return err
256257
}
@@ -1103,6 +1104,33 @@ func (s *StackManager) PrintStackInfo() error {
11031104
return nil
11041105
}
11051106

1107+
// IsRunning prints to the stdout, the stack name and it status as "running" or "not_running".
1108+
func (s *StackManager) IsRunning() error {
1109+
output, err := docker.RunDockerComposeCommandReturnsStdout(s.Stack.StackDir, "ps")
1110+
if err != nil {
1111+
return err
1112+
}
1113+
1114+
formatHeader := "\n %s\t%s\t "
1115+
formatBody := "\n %s\t%s\t"
1116+
1117+
w := new(tabwriter.Writer)
1118+
w.Init(os.Stdout, 8, 8, 8, '\t', 0)
1119+
1120+
s.once.Do(func() {
1121+
fmt.Fprintf(w, formatHeader, "STACK", "STATUS")
1122+
})
1123+
1124+
if strings.Contains(string(output), s.Stack.Name) { // if the output contains the stack name, it means the container is running.
1125+
fmt.Fprintf(w, formatBody, s.Stack.Name, "running")
1126+
} else {
1127+
fmt.Fprintf(w, formatBody, s.Stack.Name, "not_running")
1128+
}
1129+
fmt.Fprintln(w)
1130+
w.Flush()
1131+
return nil
1132+
}
1133+
11061134
func (s *StackManager) disableFireflyCoreContainers() error {
11071135
compose := s.buildDockerCompose()
11081136
for _, member := range s.Stack.Members {

0 commit comments

Comments
 (0)