refactor: client pkg with new context interaction
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
fce1ab6c02
commit
dd86ec4ca8
141
client/client.go
141
client/client.go
|
@ -1,22 +1,14 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
dCliCommand "github.com/docker/cli/cli/command"
|
"github.com/docker/docker/client"
|
||||||
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"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewClientWithContext(contextName string) (*dClient.Client, error) {
|
func NewClientWithContext(contextName string) (*client.Client, error) {
|
||||||
context, err := GetContext(contextName)
|
context, err := GetContext(contextName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -34,142 +26,27 @@ func NewClientWithContext(contextName string) (*dClient.Client, error) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var clientOpts []dClient.Opt
|
var clientOpts []client.Opt
|
||||||
|
|
||||||
clientOpts = append(clientOpts,
|
clientOpts = append(clientOpts,
|
||||||
dClient.WithHTTPClient(httpClient),
|
client.WithHTTPClient(httpClient),
|
||||||
dClient.WithHost(helper.Host),
|
client.WithHost(helper.Host),
|
||||||
dClient.WithDialContext(helper.Dialer),
|
client.WithDialContext(helper.Dialer),
|
||||||
)
|
)
|
||||||
|
|
||||||
// FIXME: Maybe don't have this variable here and load it beforehand
|
// FIXME: Maybe don't have this variable here and load it beforehand
|
||||||
version := os.Getenv("DOCKER_API_VERSION")
|
version := os.Getenv("DOCKER_API_VERSION")
|
||||||
|
|
||||||
if version != "" {
|
if version != "" {
|
||||||
clientOpts = append(clientOpts, dClient.WithVersion(version))
|
clientOpts = append(clientOpts, client.WithVersion(version))
|
||||||
} else {
|
} else {
|
||||||
clientOpts = append(clientOpts, dClient.WithAPIVersionNegotiation())
|
clientOpts = append(clientOpts, client.WithAPIVersionNegotiation())
|
||||||
}
|
}
|
||||||
|
|
||||||
cl, err := dClient.NewClientWithOpts(clientOpts...)
|
cl, err := client.NewClientWithOpts(clientOpts...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatalf("unable to create Docker client: %s", err)
|
logrus.Fatalf("unable to create Docker client: %s", err)
|
||||||
}
|
}
|
||||||
return cl, nil
|
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 {
|
|
||||||
return dCliContextStore.Metadata{}, err
|
|
||||||
}
|
|
||||||
return ctx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetContextEndpoint(ctx dCliContextStore.Metadata) (string, error) {
|
|
||||||
// safe to use docker key hardcoded since abra doesn't use k8s... yet...
|
|
||||||
endpointmeta, ok := ctx.Endpoints["docker"].(dContext.EndpointMetaBase)
|
|
||||||
if !ok {
|
|
||||||
err := errors.New("context lacks Docker endpoint")
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return endpointmeta.Host, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultDockerContextStore() *dCliCommand.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 := dCliConfig.LoadDefaultConfigFile(stderr)
|
|
||||||
contextDir := dCliConfig.ContextStoreDir()
|
|
||||||
storeConfig := dCliCommand.DefaultContextStoreConfig()
|
|
||||||
store := newContextStore(contextDir, storeConfig)
|
|
||||||
|
|
||||||
dockerContextStore := &dCliCommand.ContextStoreWithDefault{
|
|
||||||
Store: store,
|
|
||||||
Resolver: func() (*dCliCommand.DefaultContext, error) {
|
|
||||||
// nil for the Opts because it works without it and its a cli thing
|
|
||||||
return dCliCommand.ResolveDefaultContext(nil, dockerConfig, storeConfig, stderr)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return dockerContextStore
|
|
||||||
}
|
|
||||||
|
|
||||||
func newContextStore(dir string, config dCliContextStore.Config) dCliContextStore.Store {
|
|
||||||
return dCliContextStore.New(dir, config)
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/cli/cli/connhelper"
|
"github.com/docker/cli/cli/connhelper"
|
||||||
|
"github.com/docker/cli/cli/context/docker"
|
||||||
|
dCliContextStore "github.com/docker/cli/cli/context/store"
|
||||||
|
dClient "github.com/docker/docker/client"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,3 +16,30 @@ func newConnectionHelper(daemonURL string) *connhelper.ConnectionHelper {
|
||||||
}
|
}
|
||||||
return helper
|
return helper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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 := 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 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) {
|
||||||
|
// 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
|
||||||
|
}
|
Reference in New Issue