178 lines
4.4 KiB
Go
178 lines
4.4 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"coopcloud.tech/abra/cli/internal"
|
|
appPkg "coopcloud.tech/abra/pkg/app"
|
|
"coopcloud.tech/abra/pkg/autocomplete"
|
|
"coopcloud.tech/abra/pkg/client"
|
|
"coopcloud.tech/abra/pkg/config"
|
|
"coopcloud.tech/abra/pkg/formatter"
|
|
"coopcloud.tech/abra/pkg/log"
|
|
abraService "coopcloud.tech/abra/pkg/service"
|
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
|
dockerFormatter "github.com/docker/cli/cli/command/formatter"
|
|
containerTypes "github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/api/types/filters"
|
|
dockerClient "github.com/docker/docker/client"
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
var appPsCommand = cli.Command{
|
|
Name: "ps",
|
|
Aliases: []string{"p"},
|
|
Usage: "Check app status",
|
|
UsageText: "abra app ps <domain> [options]",
|
|
Description: "Show status of a deployed app.",
|
|
Flags: []cli.Flag{
|
|
internal.MachineReadableFlag,
|
|
internal.ChaosFlag,
|
|
internal.OfflineFlag,
|
|
},
|
|
Before: internal.SubCommandBefore,
|
|
ShellComplete: autocomplete.AppNameComplete,
|
|
HideHelp: true,
|
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
|
app := internal.ValidateApp(cmd)
|
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
cl, err := client.New(app.Server)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if !deployMeta.IsDeployed {
|
|
log.Fatalf("%s is not deployed?", app.Name)
|
|
}
|
|
|
|
chaosVersion := config.CHAOS_DEFAULT
|
|
statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true)
|
|
if statusMeta, ok := statuses[app.StackName()]; ok {
|
|
if isChaos, exists := statusMeta["chaos"]; exists && isChaos == "true" {
|
|
chaosVersion, err = app.Recipe.ChaosVersion()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
showPSOutput(app, cl, deployMeta.Version, chaosVersion)
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
// showPSOutput renders ps output.
|
|
func showPSOutput(app appPkg.App, cl *dockerClient.Client, deployedVersion, chaosVersion string) {
|
|
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return
|
|
}
|
|
|
|
deployOpts := stack.Deploy{
|
|
Composefiles: composeFiles,
|
|
Namespace: app.StackName(),
|
|
Prune: false,
|
|
ResolveImage: stack.ResolveImageAlways,
|
|
}
|
|
compose, err := appPkg.GetAppComposeConfig(app.Name, deployOpts, app.Env)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return
|
|
}
|
|
|
|
var rows [][]string
|
|
allContainerStats := make(map[string]map[string]string)
|
|
for _, service := range compose.Services {
|
|
filters := filters.NewArgs()
|
|
filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), service.Name))
|
|
|
|
containers, err := cl.ContainerList(context.Background(), containerTypes.ListOptions{Filters: filters})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return
|
|
}
|
|
|
|
var containerStats map[string]string
|
|
if len(containers) == 0 {
|
|
containerStats = map[string]string{
|
|
"version": deployedVersion,
|
|
"chaos": chaosVersion,
|
|
"service": service.Name,
|
|
"image": "unknown",
|
|
"created": "unknown",
|
|
"status": "unknown",
|
|
"state": "unknown",
|
|
"ports": "unknown",
|
|
}
|
|
} else {
|
|
container := containers[0]
|
|
containerStats = map[string]string{
|
|
"version": deployedVersion,
|
|
"chaos": chaosVersion,
|
|
"service": abraService.ContainerToServiceName(container.Names, app.StackName()),
|
|
"image": formatter.RemoveSha(container.Image),
|
|
"created": formatter.HumanDuration(container.Created),
|
|
"status": container.Status,
|
|
"state": container.State,
|
|
"ports": dockerFormatter.DisplayablePorts(container.Ports),
|
|
}
|
|
}
|
|
|
|
allContainerStats[containerStats["service"]] = containerStats
|
|
|
|
row := []string{
|
|
containerStats["service"],
|
|
containerStats["image"],
|
|
containerStats["created"],
|
|
containerStats["status"],
|
|
containerStats["state"],
|
|
containerStats["ports"],
|
|
}
|
|
|
|
rows = append(rows, row)
|
|
}
|
|
|
|
if internal.MachineReadable {
|
|
jsonstring, err := json.Marshal(allContainerStats)
|
|
if err != nil {
|
|
log.Fatal("unable to convert to JSON: %s", err)
|
|
}
|
|
fmt.Println(string(jsonstring))
|
|
return
|
|
}
|
|
|
|
table, err := formatter.CreateTable()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
headers := []string{
|
|
"SERVICE",
|
|
"IMAGE",
|
|
"CREATED",
|
|
"STATUS",
|
|
"STATE",
|
|
"PORTS",
|
|
}
|
|
|
|
table.
|
|
Headers(headers...).
|
|
Rows(rows...)
|
|
|
|
fmt.Println(table)
|
|
|
|
log.Infof("VERSION: %s CHAOS: %s", deployedVersion, chaosVersion)
|
|
}
|