From b089109c94173a549e6e90d3336285278e1cdf8a Mon Sep 17 00:00:00 2001 From: decentral1se Date: Mon, 23 Jan 2023 14:56:34 +0100 Subject: [PATCH] fix: more robust docker context problem handling See https://git.coopcloud.tech/coop-cloud/organising/issues/325 See https://git.coopcloud.tech/coop-cloud/organising/issues/340 --- cli/app/list.go | 5 ++++ cli/internal/new.go | 5 ++++ cli/internal/validate.go | 5 ++++ cli/server/list.go | 20 +++++++++++++++- pkg/context/context.go | 32 ++++++++++++++++++++++++++ pkg/upstream/commandconn/connection.go | 5 ++++ 6 files changed, 71 insertions(+), 1 deletion(-) diff --git a/cli/app/list.go b/cli/app/list.go index 4810e56f..d38626cb 100644 --- a/cli/app/list.go +++ b/cli/app/list.go @@ -8,6 +8,7 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/context" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/ssh" @@ -97,6 +98,10 @@ can take some time. alreadySeen := make(map[string]bool) for _, app := range apps { if _, ok := alreadySeen[app.Server]; !ok { + if err := context.HasDockerContext(app.Server); err != nil { + logrus.Fatal(err) + } + if err := ssh.EnsureHostKey(app.Server); err != nil { logrus.Fatal(fmt.Sprintf(internal.SSHFailMsg, app.Server)) } diff --git a/cli/internal/new.go b/cli/internal/new.go index cdeb9f0b..56b4c681 100644 --- a/cli/internal/new.go +++ b/cli/internal/new.go @@ -6,6 +6,7 @@ import ( "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/context" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/jsontable" "coopcloud.tech/abra/pkg/recipe" @@ -146,6 +147,10 @@ func NewAction(c *cli.Context) error { var secrets AppSecrets var secretTable *jsontable.JSONTable if Secrets { + if err := context.HasDockerContext(NewAppServer); err != nil { + logrus.Fatal(err) + } + if err := ssh.EnsureHostKey(NewAppServer); err != nil { logrus.Fatal(err) } diff --git a/cli/internal/validate.go b/cli/internal/validate.go index a60ccf89..02a024de 100644 --- a/cli/internal/validate.go +++ b/cli/internal/validate.go @@ -8,6 +8,7 @@ import ( "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/context" "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/ssh" "github.com/AlecAivazis/survey/v2" @@ -138,6 +139,10 @@ func ValidateApp(c *cli.Context) config.App { logrus.Fatal(err) } + if err := context.HasDockerContext(app.Server); err != nil { + logrus.Fatal(err) + } + if err := ssh.EnsureHostKey(app.Server); err != nil { logrus.Fatal(err) } diff --git a/cli/server/list.go b/cli/server/list.go index 32e53f8e..a9f03d20 100644 --- a/cli/server/list.go +++ b/cli/server/list.go @@ -12,11 +12,20 @@ import ( "github.com/urfave/cli" ) +var problemsFilter bool + +var problemsFilterFlag = &cli.BoolFlag{ + Name: "problems, p", + Usage: "Show only servers with potential connection problems", + Destination: &problemsFilter, +} + var serverListCommand = cli.Command{ Name: "list", Aliases: []string{"ls"}, Usage: "List managed servers", Flags: []cli.Flag{ + problemsFilterFlag, internal.DebugFlag, internal.MachineReadableFlag, }, @@ -48,6 +57,7 @@ var serverListCommand = cli.Command{ // No local context found, we can continue safely continue } + if ctx.Name == serverName { sp, err := ssh.ParseURL(endpoint) if err != nil { @@ -56,6 +66,7 @@ var serverListCommand = cli.Command{ row = []string{serverName, sp.Host, sp.User, sp.Port} } } + if len(row) == 0 { if serverName == "default" { row = []string{serverName, "local", "n/a", "n/a"} @@ -63,7 +74,14 @@ var serverListCommand = cli.Command{ row = []string{serverName, "unknown", "unknown", "unknown"} } } - table.Append(row) + + if problemsFilter { + if row[1] == "unknown" { + table.Append(row) + } + } else { + table.Append(row) + } } return nil diff --git a/pkg/context/context.go b/pkg/context/context.go index 75417aee..3412180b 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -2,6 +2,7 @@ package context import ( "errors" + "fmt" "github.com/docker/cli/cli/command" dConfig "github.com/docker/cli/cli/config" @@ -42,3 +43,34 @@ func GetContextEndpoint(ctx contextStore.Metadata) (string, error) { func newContextStore(dir string, config contextStore.Config) contextStore.Store { return contextStore.New(dir, config) } + +// MissingContextMsg helps end-uers debug missing docker context issues. +var missingContextMsg = `unable to find Docker context for %s? + +Please run "abra server ls" to confirm. If you see "unknown" in the table +output then you need to run the following command: + + abra server add %s + +See "abra server add --help" for more. +` + +// HasDockerContext figures out if a local setup has a working docker context +// configuration or not. This usually tells us if they'll be able to make a SSH +// connection to a server or not and can be a useful way to signal to end-users +// that they need to fix something up if missing. +func HasDockerContext(serverName string) error { + dockerContextStore := NewDefaultDockerContextStore() + contexts, err := dockerContextStore.Store.List() + if err != nil { + return err + } + + for _, ctx := range contexts { + if ctx.Name == serverName { + return nil + } + } + + return fmt.Errorf(missingContextMsg, serverName, serverName) +} diff --git a/pkg/upstream/commandconn/connection.go b/pkg/upstream/commandconn/connection.go index 6f632a6e..80b52a75 100644 --- a/pkg/upstream/commandconn/connection.go +++ b/pkg/upstream/commandconn/connection.go @@ -6,6 +6,7 @@ import ( "net" "net/url" + ctxPkg "coopcloud.tech/abra/pkg/context" sshPkg "coopcloud.tech/abra/pkg/ssh" "github.com/docker/cli/cli/connhelper" "github.com/docker/cli/cli/connhelper/ssh" @@ -36,6 +37,10 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*connhelper.Conne return nil, errors.Wrap(err, "ssh host connection is not valid") } + if err := ctxPkg.HasDockerContext(ctxConnDetails.Host); err != nil { + return nil, err + } + if err := sshPkg.EnsureHostKey(ctxConnDetails.Host); err != nil { return nil, err }