All checks were successful
continuous-integration/drone/push Build is passing
This is an attempt to set sensible timeouts on abra connections. This might not be the last word on this but it seems that SSH connections now bail out correctly and other kinds of commands don't explode (e.g. logs). Closes coop-cloud/organising#222. Closes coop-cloud/organising#218.
129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
package client
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
commandconnPkg "coopcloud.tech/abra/pkg/upstream/commandconn"
|
|
command "github.com/docker/cli/cli/command"
|
|
dConfig "github.com/docker/cli/cli/config"
|
|
context "github.com/docker/cli/cli/context"
|
|
"github.com/docker/cli/cli/context/docker"
|
|
contextStore "github.com/docker/cli/cli/context/store"
|
|
cliflags "github.com/docker/cli/cli/flags"
|
|
"github.com/moby/term"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type Context = contextStore.Metadata
|
|
|
|
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 := createContext(contextName, host); err != nil {
|
|
return err
|
|
}
|
|
logrus.Debugf("created the '%s' context", contextName)
|
|
return nil
|
|
}
|
|
|
|
// createContext interacts with Docker Context to create a Docker context config
|
|
func createContext(name string, host string) error {
|
|
s := NewDefaultDockerContextStore()
|
|
contextMetadata := contextStore.Metadata{
|
|
Endpoints: make(map[string]interface{}),
|
|
Name: name,
|
|
}
|
|
|
|
contextTLSData := contextStore.ContextTLSData{
|
|
Endpoints: make(map[string]contextStore.EndpointTLSData),
|
|
}
|
|
|
|
dockerEP, dockerTLS, err := commandconnPkg.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 DeleteContext(name string) error {
|
|
if name == "default" {
|
|
return errors.New("context 'default' cannot be removed")
|
|
}
|
|
|
|
if _, err := GetContext(name); err != nil {
|
|
return err
|
|
}
|
|
|
|
// remove any context that might be loaded
|
|
// TODO: Check if the context we are removing is the active one rather than doing it all the time
|
|
cfg := dConfig.LoadDefaultConfigFile(nil)
|
|
cfg.CurrentContext = ""
|
|
if err := cfg.Save(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return NewDefaultDockerContextStore().Remove(name)
|
|
}
|
|
|
|
func GetContext(contextName string) (contextStore.Metadata, error) {
|
|
ctx, err := NewDefaultDockerContextStore().GetMetadata(contextName)
|
|
if err != nil {
|
|
return contextStore.Metadata{}, err
|
|
}
|
|
|
|
return ctx, nil
|
|
}
|
|
|
|
func GetContextEndpoint(ctx contextStore.Metadata) (string, error) {
|
|
endpointmeta, ok := ctx.Endpoints["docker"].(context.EndpointMetaBase)
|
|
if !ok {
|
|
err := errors.New("context lacks Docker endpoint")
|
|
return "", err
|
|
}
|
|
return endpointmeta.Host, nil
|
|
}
|
|
|
|
func newContextStore(dir string, config contextStore.Config) contextStore.Store {
|
|
return contextStore.New(dir, config)
|
|
}
|
|
|
|
func NewDefaultDockerContextStore() *command.ContextStoreWithDefault {
|
|
_, _, stderr := term.StdStreams()
|
|
dockerConfig := dConfig.LoadDefaultConfigFile(stderr)
|
|
contextDir := dConfig.ContextStoreDir()
|
|
storeConfig := command.DefaultContextStoreConfig()
|
|
store := newContextStore(contextDir, storeConfig)
|
|
|
|
opts := &cliflags.CommonOptions{Context: "default"}
|
|
|
|
dockerContextStore := &command.ContextStoreWithDefault{
|
|
Store: store,
|
|
Resolver: func() (*command.DefaultContext, error) {
|
|
return command.ResolveDefaultContext(opts, dockerConfig, storeConfig, stderr)
|
|
},
|
|
}
|
|
|
|
return dockerContextStore
|
|
}
|