129 lines
3.0 KiB
Go
129 lines
3.0 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"coopcloud.tech/abra/cli/internal"
|
|
"coopcloud.tech/abra/pkg/client"
|
|
"coopcloud.tech/abra/pkg/config"
|
|
"coopcloud.tech/abra/pkg/upstream/container"
|
|
"github.com/docker/cli/cli/command"
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/filters"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
var user string
|
|
var userFlag = &cli.StringFlag{
|
|
Name: "user",
|
|
Value: "",
|
|
Destination: &user,
|
|
}
|
|
|
|
var noTTY bool
|
|
var noTTYFlag = &cli.BoolFlag{
|
|
Name: "no-tty",
|
|
Value: false,
|
|
Destination: &noTTY,
|
|
}
|
|
|
|
var appRunCommand = &cli.Command{
|
|
Name: "run",
|
|
Flags: []cli.Flag{
|
|
noTTYFlag,
|
|
userFlag,
|
|
},
|
|
Aliases: []string{"r"},
|
|
ArgsUsage: "<service> <args>...",
|
|
Usage: "Run a command in a service container",
|
|
Action: func(c *cli.Context) error {
|
|
app := internal.ValidateApp(c)
|
|
|
|
if c.Args().Len() < 2 {
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no <service> provided?"))
|
|
}
|
|
|
|
if c.Args().Len() < 3 {
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no <args> provided?"))
|
|
}
|
|
|
|
cl, err := client.New(app.Server)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
serviceName := c.Args().Get(1)
|
|
stackAndServiceName := fmt.Sprintf("%s_%s", app.StackName(), serviceName)
|
|
filters := filters.NewArgs()
|
|
filters.Add("name", stackAndServiceName)
|
|
|
|
containers, err := cl.ContainerList(c.Context, types.ContainerListOptions{Filters: filters})
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if len(containers) == 0 {
|
|
logrus.Fatalf("no containers matching '%s' found?", stackAndServiceName)
|
|
}
|
|
if len(containers) > 1 {
|
|
logrus.Fatalf("expected 1 container matching '%s' but got %d", stackAndServiceName, len(containers))
|
|
}
|
|
|
|
cmd := c.Args().Slice()[2:]
|
|
execCreateOpts := types.ExecConfig{
|
|
AttachStderr: true,
|
|
AttachStdin: true,
|
|
AttachStdout: true,
|
|
Cmd: cmd,
|
|
Detach: false,
|
|
Tty: true,
|
|
}
|
|
|
|
if user != "" {
|
|
execCreateOpts.User = user
|
|
}
|
|
if noTTY {
|
|
execCreateOpts.Tty = false
|
|
}
|
|
|
|
// FIXME: an absolutely monumental hack to instantiate another command-line
|
|
// client withing our command-line client so that we pass something down
|
|
// the tubes that satisfies the necessary interface requirements. We should
|
|
// refactor our vendored container code to not require all this cruft. For
|
|
// now, It Works.
|
|
dcli, err := command.NewDockerCli()
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if err := container.RunExec(dcli, cl, containers[0].ID, &execCreateOpts); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
BashComplete: func(c *cli.Context) {
|
|
switch c.NArg() {
|
|
case 0:
|
|
appNames, err := config.GetAppNames()
|
|
if err != nil {
|
|
logrus.Warn(err)
|
|
}
|
|
for _, a := range appNames {
|
|
fmt.Println(a)
|
|
}
|
|
case 1:
|
|
appName := c.Args().First()
|
|
serviceNames, err := config.GetAppServiceNames(appName)
|
|
if err != nil {
|
|
logrus.Warn(err)
|
|
}
|
|
for _, s := range serviceNames {
|
|
fmt.Println(s)
|
|
}
|
|
}
|
|
},
|
|
}
|