package app import ( "fmt" "os" "strings" "coopcloud.tech/abra/cli/formatter" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/pkg/archive" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) var appCpCommand = &cli.Command{ Name: "cp", Aliases: []string{"c"}, ArgsUsage: " ", Usage: "Copy files to/from a running app service", Action: func(c *cli.Context) error { app := internal.ValidateApp(c) src := c.Args().Get(1) dst := c.Args().Get(2) if src == "" { logrus.Fatal("missing argument") } else if dst == "" { logrus.Fatal("missing argument") } parsedSrc := strings.SplitN(src, ":", 2) parsedDst := strings.SplitN(dst, ":", 2) errorMsg := "one of / arguments must take $SERVICE:$PATH form" if len(parsedSrc) == 2 && len(parsedDst) == 2 { logrus.Fatal(errorMsg) } else if len(parsedSrc) != 2 { if len(parsedDst) != 2 { logrus.Fatal(errorMsg) } } else if len(parsedDst) != 2 { if len(parsedSrc) != 2 { logrus.Fatal(errorMsg) } } var service string var srcPath string var dstPath string isToContainer := false // if len(parsedSrc) == 2 { service = parsedSrc[0] srcPath = parsedSrc[1] dstPath = dst logrus.Debugf("assuming transfer is coming FROM the container") } else if len(parsedDst) == 2 { service = parsedDst[0] dstPath = parsedDst[1] srcPath = src isToContainer = true // logrus.Debugf("assuming transfer is going TO the container") } appFiles, err := config.LoadAppFiles("") if err != nil { logrus.Fatal(err) } appEnv, err := config.GetApp(appFiles, app.Name) if err != nil { logrus.Fatal(err) } cl, err := client.New(app.Server) if err != nil { logrus.Fatal(err) } filters := filters.NewArgs() filters.Add("name", fmt.Sprintf("%s_%s", appEnv.StackName(), service)) containers, err := cl.ContainerList(c.Context, types.ContainerListOptions{Filters: filters}) if err != nil { logrus.Fatal(err) } if len(containers) != 1 { logrus.Fatalf("expected 1 container but got %v", len(containers)) } container := containers[0] logrus.Debugf("retrieved '%s' as target container on '%s'", formatter.ShortenID(container.ID), app.Server) if isToContainer { if _, err := os.Stat(srcPath); err != nil { logrus.Fatalf("'%s' does not exist?", srcPath) } toTarOpts := &archive.TarOptions{NoOverwriteDirNonDir: true, Compression: archive.Gzip} content, err := archive.TarWithOptions(srcPath, toTarOpts) if err != nil { logrus.Fatal(err) } copyOpts := types.CopyToContainerOptions{AllowOverwriteDirWithFile: false, CopyUIDGID: false} if err := cl.CopyToContainer(c.Context, container.ID, dstPath, content, copyOpts); err != nil { logrus.Fatal(err) } } else { content, _, err := cl.CopyFromContainer(c.Context, container.ID, srcPath) if err != nil { logrus.Fatal(err) } defer content.Close() fromTarOpts := &archive.TarOptions{NoOverwriteDirNonDir: true, Compression: archive.Gzip} if err := archive.Untar(content, dstPath, fromTarOpts); err != nil { logrus.Fatal(err) } } return nil }, }