package server import ( "context" "errors" "os/exec" "os/user" "strings" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/server" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) var local bool var localFlag = &cli.BoolFlag{ Name: "local", Aliases: []string{"L"}, Value: false, Usage: "Set up the local server", Destination: &local, } var serverAddCommand = &cli.Command{ Name: "add", Usage: "Add a new server", Description: ` This command adds a new server that abra will communicate with, to deploy apps. If "--local" is passed, then Abra assumes that the current local server is intended as the target server. Otherwise, you may specify a remote server. The argument must be a publicy accessible domain name which points to your server. You should have SSH access to this server, Abra will assume port 22 and will use your current system username to make an initial connection. You can use the and arguments to adjust this. For example: abra server add varia.zone glodemodem 12345 Abra will construct the following SSH connection string then: ssh://globemodem@varia.zone:12345 All communication between Abra and the server will use this SSH connection. `, Aliases: []string{"a"}, Flags: []cli.Flag{ localFlag, }, ArgsUsage: " [] []", Action: func(c *cli.Context) error { if c.Args().Len() == 2 && !local { err := errors.New("missing arguments or '--local'") internal.ShowSubcommandHelpAndError(c, err) } if c.Args().Get(2) != "" && local { err := errors.New("cannot use '' and '--local' together") internal.ShowSubcommandHelpAndError(c, err) } domainName := "default" if local { if err := server.CreateServerDir(domainName); err != nil { logrus.Fatal(err) } if _, err := exec.LookPath("docker"); err != nil { return errors.New("docker command not found on $PATH, is it installed?") } logrus.Info("local server has been added") return nil } domainName = internal.ValidateDomain(c) var username string var port string username = c.Args().Get(1) if username == "" { systemUser, err := user.Current() if err != nil { logrus.Fatal(err) } username = systemUser.Username } port = c.Args().Get(2) if port == "" { port = "22" } store := client.NewDefaultDockerContextStore() contexts, err := store.Store.List() if err != nil { logrus.Fatal(err) } for _, context := range contexts { if context.Name == domainName { logrus.Fatalf("server at '%s' already exists?", domainName) } } logrus.Debugf("creating context with domain '%s', username '%s' and port '%s'", domainName, username, port) if err := client.CreateContext(domainName, username, port); err != nil { logrus.Fatal(err) } ctx := context.Background() cl, err := client.New(domainName) if err != nil { logrus.Warn("cleaning up context due to connection failure") if err := client.DeleteContext(domainName); err != nil { logrus.Fatal(err) } logrus.Fatal(err) } if _, err := cl.Info(ctx); err != nil { if strings.Contains(err.Error(), "command not found") { logrus.Fatalf("docker is not installed on '%s'?", domainName) } else { logrus.Warn("cleaning up context due to connection failure") if err := client.DeleteContext(domainName); err != nil { logrus.Fatal(err) } logrus.Fatalf("unable to make a connection to '%s'?", domainName) } logrus.Debug(err) } logrus.Debugf("remote connection to '%s' is definitely up", domainName) if err := server.CreateServerDir(domainName); err != nil { logrus.Fatal(err) } logrus.Infof("server at '%s' has been added", domainName) return nil }, }