2021-07-22 14:31:39 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
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"
|
|
|
|
"github.com/moby/term"
|
2021-09-10 22:54:02 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2021-07-22 14:31:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
logrus.Debugf("created the '%s' context", contextName)
|
2021-07-22 14:31:39 +00:00
|
|
|
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,
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
contextTLSData := contextStore.ContextTLSData{
|
|
|
|
Endpoints: make(map[string]contextStore.EndpointTLSData),
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(host)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
contextMetadata.Endpoints[docker.DockerEndpoint] = dockerEP
|
|
|
|
if dockerTLS != nil {
|
|
|
|
contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerTLS
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.CreateOrUpdate(contextMetadata); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
if err := s.ResetTLSMaterial(name, &contextTLSData); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-07-22 16:38:44 +00:00
|
|
|
func DeleteContext(name string) error {
|
|
|
|
if name == "default" {
|
|
|
|
return errors.New("context 'default' cannot be removed")
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 16:38:44 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
func GetContext(contextName string) (contextStore.Metadata, error) {
|
|
|
|
ctx, err := NewDefaultDockerContextStore().GetMetadata(contextName)
|
|
|
|
if err != nil {
|
|
|
|
return contextStore.Metadata{}, err
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
|
2021-07-22 14:31:39 +00:00
|
|
|
return ctx, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetContextEndpoint(ctx contextStore.Metadata) (string, error) {
|
|
|
|
// safe to use docker key hardcoded since abra doesn't use k8s... yet...
|
|
|
|
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 {
|
|
|
|
// Grabbing the stderr from Docker commands
|
|
|
|
// Much easier to fit this into the code we are using to replicate docker cli commands
|
|
|
|
_, _, stderr := term.StdStreams()
|
|
|
|
// TODO: Look into custom docker configs in case users want that
|
|
|
|
dockerConfig := dConfig.LoadDefaultConfigFile(stderr)
|
|
|
|
contextDir := dConfig.ContextStoreDir()
|
|
|
|
storeConfig := command.DefaultContextStoreConfig()
|
|
|
|
store := newContextStore(contextDir, storeConfig)
|
|
|
|
|
|
|
|
dockerContextStore := &command.ContextStoreWithDefault{
|
|
|
|
Store: store,
|
|
|
|
Resolver: func() (*command.DefaultContext, error) {
|
|
|
|
// nil for the Opts because it works without it and its a cli thing
|
|
|
|
return command.ResolveDefaultContext(nil, dockerConfig, storeConfig, stderr)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return dockerContextStore
|
|
|
|
}
|