diff --git a/cli/app/cp.go b/cli/app/cp.go index 00b9db8f..af24f91c 100644 --- a/cli/app/cp.go +++ b/cli/app/cp.go @@ -1,11 +1,19 @@ package app import ( + "fmt" "os" "strings" + "coopcloud.tech/abra/cli/formatter" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" + "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/container" + "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" ) @@ -75,7 +83,7 @@ And if you want to copy that file back to your current working directory locally logrus.Fatalf("%s does not exist locally?", dstPath) } } - err := internal.ConfigureAndCp(c, app, srcPath, dstPath, service, isToContainer) + err := configureAndCp(c, app, srcPath, dstPath, service, isToContainer) if err != nil { logrus.Fatal(err) } @@ -84,3 +92,64 @@ And if you want to copy that file back to your current working directory locally }, BashComplete: autocomplete.AppNameComplete, } + +func configureAndCp( + c *cli.Context, + app config.App, + srcPath string, + dstPath string, + service string, + isToContainer bool) error { + 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)) + + container, err := container.GetContainer(c.Context, cl, filters, true) + if err != nil { + logrus.Fatal(err) + } + + 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 +} diff --git a/cli/internal/copy.go b/cli/internal/copy.go deleted file mode 100644 index 71899761..00000000 --- a/cli/internal/copy.go +++ /dev/null @@ -1,71 +0,0 @@ -package internal - -import ( - "fmt" - "os" - - "coopcloud.tech/abra/cli/formatter" - "coopcloud.tech/abra/pkg/client" - "coopcloud.tech/abra/pkg/config" - "coopcloud.tech/abra/pkg/container" - "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" -) - -func ConfigureAndCp(c *cli.Context, app config.App, srcPath string, dstPath string, service string, isToContainer bool) error { - 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)) - - container, err := container.GetContainer(c.Context, cl, filters, true) - if err != nil { - logrus.Fatal(err) - } - - 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 -} diff --git a/cli/internal/record.go b/cli/internal/record.go deleted file mode 100644 index 9a3ef0ec..00000000 --- a/cli/internal/record.go +++ /dev/null @@ -1,106 +0,0 @@ -package internal - -import ( - "errors" - "fmt" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" -) - -// EnsureDNSProvider ensures a DNS provider is chosen. -func EnsureDNSProvider() error { - if DNSProvider == "" && !NoInput { - prompt := &survey.Select{ - Message: "Select DNS provider", - Options: []string{"gandi"}, - } - - if err := survey.AskOne(prompt, &DNSProvider); err != nil { - return err - } - } - - if DNSProvider == "" { - return fmt.Errorf("missing DNS provider?") - } - - return nil -} - -// EnsureDNSTypeFlag ensures a DNS type flag is present. -func EnsureDNSTypeFlag(c *cli.Context) error { - if DNSType == "" && !NoInput { - prompt := &survey.Input{ - Message: "Specify DNS record type", - Default: "A", - } - if err := survey.AskOne(prompt, &DNSType); err != nil { - return err - } - } - - if DNSType == "" { - ShowSubcommandHelpAndError(c, errors.New("no record type provided")) - } - - return nil -} - -// EnsureDNSNameFlag ensures a DNS name flag is present. -func EnsureDNSNameFlag(c *cli.Context) error { - if DNSName == "" && !NoInput { - prompt := &survey.Input{ - Message: "Specify DNS record name", - Default: "mysubdomain", - } - if err := survey.AskOne(prompt, &DNSName); err != nil { - return err - } - } - - if DNSName == "" { - ShowSubcommandHelpAndError(c, errors.New("no record name provided")) - } - - return nil -} - -// EnsureDNSValueFlag ensures a DNS value flag is present. -func EnsureDNSValueFlag(c *cli.Context) error { - if DNSValue == "" && !NoInput { - prompt := &survey.Input{ - Message: "Specify DNS record value", - Default: "192.168.1.2", - } - if err := survey.AskOne(prompt, &DNSValue); err != nil { - return err - } - } - - if DNSName == "" { - ShowSubcommandHelpAndError(c, errors.New("no record value provided")) - } - - return nil -} - -// EnsureZoneArgument ensures a zone argument is present. -func EnsureZoneArgument(c *cli.Context) (string, error) { - var zone string - if c.Args().First() == "" && !NoInput { - prompt := &survey.Input{ - Message: "Specify a domain name zone", - Default: "example.com", - } - if err := survey.AskOne(prompt, &zone); err != nil { - return zone, err - } - } - - if zone == "" { - ShowSubcommandHelpAndError(c, errors.New("no zone value provided")) - } - - return zone, nil -} diff --git a/cli/internal/server.go b/cli/internal/server.go deleted file mode 100644 index 83641a38..00000000 --- a/cli/internal/server.go +++ /dev/null @@ -1,208 +0,0 @@ -package internal - -import ( - "fmt" - "os" - "strings" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" -) - -// EnsureServerProvider ensures a 3rd party server provider is chosen. -func EnsureServerProvider() error { - if ServerProvider == "" && !NoInput { - prompt := &survey.Select{ - Message: "Select server provider", - Options: []string{"capsul", "hetzner-cloud"}, - } - - if err := survey.AskOne(prompt, &ServerProvider); err != nil { - return err - } - } - - if ServerProvider == "" { - return fmt.Errorf("missing server provider?") - } - - return nil -} - -// EnsureNewCapsulVPSFlags ensure all flags are present. -func EnsureNewCapsulVPSFlags(c *cli.Context) error { - if CapsulName == "" && !NoInput { - prompt := &survey.Input{ - Message: "specify capsul name", - } - if err := survey.AskOne(prompt, &CapsulName); err != nil { - return err - } - } - - if !NoInput { - prompt := &survey.Input{ - Message: "specify capsul instance URL", - Default: CapsulInstanceURL, - } - if err := survey.AskOne(prompt, &CapsulInstanceURL); err != nil { - return err - } - } - - if !NoInput { - prompt := &survey.Input{ - Message: "specify capsul type", - Default: CapsulType, - } - if err := survey.AskOne(prompt, &CapsulType); err != nil { - return err - } - } - - if !NoInput { - prompt := &survey.Input{ - Message: "specify capsul image", - Default: CapsulImage, - } - if err := survey.AskOne(prompt, &CapsulImage); err != nil { - return err - } - } - - if len(CapsulSSHKeys.Value()) == 0 && !NoInput { - var sshKeys string - prompt := &survey.Input{ - Message: "specify capsul SSH keys (e.g. me@foo.com)", - Default: "", - } - if err := survey.AskOne(prompt, &CapsulSSHKeys); err != nil { - return err - } - CapsulSSHKeys = *cli.NewStringSlice(strings.Split(sshKeys, ",")...) - } - - if CapsulAPIToken == "" && !NoInput { - token, ok := os.LookupEnv("CAPSUL_TOKEN") - if !ok { - prompt := &survey.Input{ - Message: "specify capsul API token", - } - if err := survey.AskOne(prompt, &CapsulAPIToken); err != nil { - return err - } - } else { - CapsulAPIToken = token - } - } - - if CapsulName == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul name?")) - } - if CapsulInstanceURL == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul instance url?")) - } - if CapsulType == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul type?")) - } - if CapsulImage == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul image?")) - } - if len(CapsulSSHKeys.Value()) == 0 { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul ssh keys?")) - } - if CapsulAPIToken == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul API token?")) - } - - return nil -} - -// EnsureNewHetznerCloudVPSFlags ensure all flags are present. -func EnsureNewHetznerCloudVPSFlags(c *cli.Context) error { - if HetznerCloudName == "" && !NoInput { - prompt := &survey.Input{ - Message: "specify hetzner cloud VPS name", - } - if err := survey.AskOne(prompt, &HetznerCloudName); err != nil { - return err - } - } - - if !NoInput { - prompt := &survey.Input{ - Message: "specify hetzner cloud VPS type", - Default: HetznerCloudType, - } - if err := survey.AskOne(prompt, &HetznerCloudType); err != nil { - return err - } - } - - if !NoInput { - prompt := &survey.Input{ - Message: "specify hetzner cloud VPS image", - Default: HetznerCloudImage, - } - if err := survey.AskOne(prompt, &HetznerCloudImage); err != nil { - return err - } - } - - if len(HetznerCloudSSHKeys.Value()) == 0 && !NoInput { - var sshKeys string - prompt := &survey.Input{ - Message: "specify hetzner cloud SSH keys (e.g. me@foo.com)", - Default: "", - } - if err := survey.AskOne(prompt, &sshKeys); err != nil { - return err - } - HetznerCloudSSHKeys = *cli.NewStringSlice(strings.Split(sshKeys, ",")...) - } - - if !NoInput { - prompt := &survey.Input{ - Message: "specify hetzner cloud VPS location", - Default: HetznerCloudLocation, - } - if err := survey.AskOne(prompt, &HetznerCloudLocation); err != nil { - return err - } - } - - if HetznerCloudAPIToken == "" && !NoInput { - token, ok := os.LookupEnv("HCLOUD_TOKEN") - if !ok { - prompt := &survey.Input{ - Message: "specify hetzner cloud API token", - } - if err := survey.AskOne(prompt, &HetznerCloudAPIToken); err != nil { - return err - } - } else { - HetznerCloudAPIToken = token - } - } - - if HetznerCloudName == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud VPS name?")) - } - if HetznerCloudType == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud VPS type?")) - } - if HetznerCloudImage == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud image?")) - } - if len(HetznerCloudSSHKeys.Value()) == 0 { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud ssh keys?")) - } - if HetznerCloudLocation == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud VPS location?")) - } - if HetznerCloudAPIToken == "" { - ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud API token?")) - } - - return nil -} diff --git a/cli/internal/validate.go b/cli/internal/validate.go index 92701140..af5348df 100644 --- a/cli/internal/validate.go +++ b/cli/internal/validate.go @@ -2,6 +2,8 @@ package internal import ( "errors" + "fmt" + "os" "strings" "coopcloud.tech/abra/pkg/app" @@ -197,3 +199,298 @@ func ValidateServer(c *cli.Context) (string, error) { return serverName, nil } + +// EnsureDNSProvider ensures a DNS provider is chosen. +func EnsureDNSProvider() error { + if DNSProvider == "" && !NoInput { + prompt := &survey.Select{ + Message: "Select DNS provider", + Options: []string{"gandi"}, + } + + if err := survey.AskOne(prompt, &DNSProvider); err != nil { + return err + } + } + + if DNSProvider == "" { + return fmt.Errorf("missing DNS provider?") + } + + return nil +} + +// EnsureDNSTypeFlag ensures a DNS type flag is present. +func EnsureDNSTypeFlag(c *cli.Context) error { + if DNSType == "" && !NoInput { + prompt := &survey.Input{ + Message: "Specify DNS record type", + Default: "A", + } + if err := survey.AskOne(prompt, &DNSType); err != nil { + return err + } + } + + if DNSType == "" { + ShowSubcommandHelpAndError(c, errors.New("no record type provided")) + } + + return nil +} + +// EnsureDNSNameFlag ensures a DNS name flag is present. +func EnsureDNSNameFlag(c *cli.Context) error { + if DNSName == "" && !NoInput { + prompt := &survey.Input{ + Message: "Specify DNS record name", + Default: "mysubdomain", + } + if err := survey.AskOne(prompt, &DNSName); err != nil { + return err + } + } + + if DNSName == "" { + ShowSubcommandHelpAndError(c, errors.New("no record name provided")) + } + + return nil +} + +// EnsureDNSValueFlag ensures a DNS value flag is present. +func EnsureDNSValueFlag(c *cli.Context) error { + if DNSValue == "" && !NoInput { + prompt := &survey.Input{ + Message: "Specify DNS record value", + Default: "192.168.1.2", + } + if err := survey.AskOne(prompt, &DNSValue); err != nil { + return err + } + } + + if DNSName == "" { + ShowSubcommandHelpAndError(c, errors.New("no record value provided")) + } + + return nil +} + +// EnsureZoneArgument ensures a zone argument is present. +func EnsureZoneArgument(c *cli.Context) (string, error) { + var zone string + if c.Args().First() == "" && !NoInput { + prompt := &survey.Input{ + Message: "Specify a domain name zone", + Default: "example.com", + } + if err := survey.AskOne(prompt, &zone); err != nil { + return zone, err + } + } + + if zone == "" { + ShowSubcommandHelpAndError(c, errors.New("no zone value provided")) + } + + return zone, nil +} + +// EnsureServerProvider ensures a 3rd party server provider is chosen. +func EnsureServerProvider() error { + if ServerProvider == "" && !NoInput { + prompt := &survey.Select{ + Message: "Select server provider", + Options: []string{"capsul", "hetzner-cloud"}, + } + + if err := survey.AskOne(prompt, &ServerProvider); err != nil { + return err + } + } + + if ServerProvider == "" { + return fmt.Errorf("missing server provider?") + } + + return nil +} + +// EnsureNewCapsulVPSFlags ensure all flags are present. +func EnsureNewCapsulVPSFlags(c *cli.Context) error { + if CapsulName == "" && !NoInput { + prompt := &survey.Input{ + Message: "specify capsul name", + } + if err := survey.AskOne(prompt, &CapsulName); err != nil { + return err + } + } + + if !NoInput { + prompt := &survey.Input{ + Message: "specify capsul instance URL", + Default: CapsulInstanceURL, + } + if err := survey.AskOne(prompt, &CapsulInstanceURL); err != nil { + return err + } + } + + if !NoInput { + prompt := &survey.Input{ + Message: "specify capsul type", + Default: CapsulType, + } + if err := survey.AskOne(prompt, &CapsulType); err != nil { + return err + } + } + + if !NoInput { + prompt := &survey.Input{ + Message: "specify capsul image", + Default: CapsulImage, + } + if err := survey.AskOne(prompt, &CapsulImage); err != nil { + return err + } + } + + if len(CapsulSSHKeys.Value()) == 0 && !NoInput { + var sshKeys string + prompt := &survey.Input{ + Message: "specify capsul SSH keys (e.g. me@foo.com)", + Default: "", + } + if err := survey.AskOne(prompt, &CapsulSSHKeys); err != nil { + return err + } + CapsulSSHKeys = *cli.NewStringSlice(strings.Split(sshKeys, ",")...) + } + + if CapsulAPIToken == "" && !NoInput { + token, ok := os.LookupEnv("CAPSUL_TOKEN") + if !ok { + prompt := &survey.Input{ + Message: "specify capsul API token", + } + if err := survey.AskOne(prompt, &CapsulAPIToken); err != nil { + return err + } + } else { + CapsulAPIToken = token + } + } + + if CapsulName == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul name?")) + } + if CapsulInstanceURL == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul instance url?")) + } + if CapsulType == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul type?")) + } + if CapsulImage == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul image?")) + } + if len(CapsulSSHKeys.Value()) == 0 { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul ssh keys?")) + } + if CapsulAPIToken == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing capsul API token?")) + } + + return nil +} + +// EnsureNewHetznerCloudVPSFlags ensure all flags are present. +func EnsureNewHetznerCloudVPSFlags(c *cli.Context) error { + if HetznerCloudName == "" && !NoInput { + prompt := &survey.Input{ + Message: "specify hetzner cloud VPS name", + } + if err := survey.AskOne(prompt, &HetznerCloudName); err != nil { + return err + } + } + + if !NoInput { + prompt := &survey.Input{ + Message: "specify hetzner cloud VPS type", + Default: HetznerCloudType, + } + if err := survey.AskOne(prompt, &HetznerCloudType); err != nil { + return err + } + } + + if !NoInput { + prompt := &survey.Input{ + Message: "specify hetzner cloud VPS image", + Default: HetznerCloudImage, + } + if err := survey.AskOne(prompt, &HetznerCloudImage); err != nil { + return err + } + } + + if len(HetznerCloudSSHKeys.Value()) == 0 && !NoInput { + var sshKeys string + prompt := &survey.Input{ + Message: "specify hetzner cloud SSH keys (e.g. me@foo.com)", + Default: "", + } + if err := survey.AskOne(prompt, &sshKeys); err != nil { + return err + } + HetznerCloudSSHKeys = *cli.NewStringSlice(strings.Split(sshKeys, ",")...) + } + + if !NoInput { + prompt := &survey.Input{ + Message: "specify hetzner cloud VPS location", + Default: HetznerCloudLocation, + } + if err := survey.AskOne(prompt, &HetznerCloudLocation); err != nil { + return err + } + } + + if HetznerCloudAPIToken == "" && !NoInput { + token, ok := os.LookupEnv("HCLOUD_TOKEN") + if !ok { + prompt := &survey.Input{ + Message: "specify hetzner cloud API token", + } + if err := survey.AskOne(prompt, &HetznerCloudAPIToken); err != nil { + return err + } + } else { + HetznerCloudAPIToken = token + } + } + + if HetznerCloudName == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud VPS name?")) + } + if HetznerCloudType == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud VPS type?")) + } + if HetznerCloudImage == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud image?")) + } + if len(HetznerCloudSSHKeys.Value()) == 0 { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud ssh keys?")) + } + if HetznerCloudLocation == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud VPS location?")) + } + if HetznerCloudAPIToken == "" { + ShowSubcommandHelpAndError(c, fmt.Errorf("missing hetzner cloud API token?")) + } + + return nil +}