From fc7dade6f8933e1999eeaba1443c3278c49221d4 Mon Sep 17 00:00:00 2001 From: Roxie Gibson Date: Thu, 22 Jul 2021 12:48:14 +0100 Subject: [PATCH] feat: server add command Interacts with and stores infomaton in the docker store at ~/.docker Equivalent to docker context add --- cli/server.go | 12 ++++++++ client/client.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/cli/server.go b/cli/server.go index 5757faa..2e2235a 100644 --- a/cli/server.go +++ b/cli/server.go @@ -58,6 +58,18 @@ var serverAddCommand = &cli.Command{ Usage: "Add a server, reachable on .", ArgsUsage: " [] []", Description: "[], [] SSH connection details", + Action: func(c *cli.Context) error { + arg_len := c.Args().Len() + args := c.Args().Slice() + if arg_len < 3 { + args = append(args, make([]string, 3-arg_len)...) + } + if err := client.CreateContext(args[0], args[1], args[2]); err != nil { + logrus.Fatal(err) + } + fmt.Println(args[0]) + return nil + }, } var serverNewCommand = &cli.Command{ diff --git a/client/client.go b/client/client.go index dd66aae..6fd5153 100644 --- a/client/client.go +++ b/client/client.go @@ -2,12 +2,14 @@ package client import ( "errors" + "fmt" "net/http" "os" dCliCommand "github.com/docker/cli/cli/command" dCliConfig "github.com/docker/cli/cli/config" dContext "github.com/docker/cli/cli/context" + "github.com/docker/cli/cli/context/docker" dCliContextStore "github.com/docker/cli/cli/context/store" dClient "github.com/docker/docker/client" "github.com/moby/term" @@ -57,6 +59,79 @@ func NewClientWithContext(contextName string) (*dClient.Client, error) { return cl, nil } +func CreateContext(contextName string, user string, port string) error { + host := contextName + if user != "" { + host = fmt.Sprintf("%s@%s", user, host) + } + if port != "" { + host = fmt.Sprintf("%s:%s", host, port) + } + host = fmt.Sprintf("ssh://%s", host) + if err := createNewContext(contextName, host); err != nil { + return err + } + return nil +} + +func createNewContext(name string, host string) error { + s := NewDefaultDockerContextStore() + contextMetadata := newContextMetadata(name) + contextTLSData := dCliContextStore.ContextTLSData{ + Endpoints: make(map[string]dCliContextStore.EndpointTLSData), + } + dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(host) + if err != nil { + return err + } + contextMetadata.Endpoints[docker.DockerEndpoint] = dockerEP + if dockerTLS != nil { + contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerTLS + } + + if err := s.CreateOrUpdate(contextMetadata); err != nil { + return err + } + if err := s.ResetTLSMaterial(name, &contextTLSData); err != nil { + return err + } + return nil +} + +func getDockerEndpoint(host string) (docker.Endpoint, error) { + skipTLSVerify := false + ep := docker.Endpoint{ + EndpointMeta: docker.EndpointMeta{ + Host: host, + SkipTLSVerify: skipTLSVerify, + }, + } + // try to resolve a docker client, validating the configuration + opts, err := ep.ClientOpts() + if err != nil { + return docker.Endpoint{}, err + } + if _, err := dClient.NewClientWithOpts(opts...); err != nil { + return docker.Endpoint{}, err + } + return ep, nil +} + +func newContextMetadata(name string) dCliContextStore.Metadata { + return dCliContextStore.Metadata{ + Endpoints: make(map[string]interface{}), + Name: name, + } +} + +func getDockerEndpointMetadataAndTLS(host string) (docker.EndpointMeta, *dCliContextStore.EndpointTLSData, error) { + ep, err := getDockerEndpoint(host) + if err != nil { + return docker.EndpointMeta{}, nil, err + } + return ep.EndpointMeta, ep.TLSData.ToStoreTLSData(), nil +} + func GetContext(contextName string) (dCliContextStore.Metadata, error) { ctx, err := NewDefaultDockerContextStore().GetMetadata(contextName) if err != nil {