Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions examples/cobra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ go build -o bin/cobra main.go
```bash
bin/cobra kube-only --tmp-dir=/tmp/my-cobra --kubeconfig=~/my.kind.kubeconfig --kubeconfig-context=kind-my --print-warning

bin/cobra ssh --ssh-user=ubuntu --ssh-host=0.0.0.0
bin/cobra ssh --tmp-dir=/tmp/my-cobra --ssh-user=ubuntu --ssh-host=0.0.0.0

bin/cobra ssh --ssh-user=ubuntu --ssh-host=0.0.0.0 --use-standalone-kube --kubeconfig=~/my.kind.kubeconfig
COBRA_SSH_MODERN_MODE=true bin/cobra ssh --tmp-dir=/tmp/my-cobra --ssh-user=ubuntu --ssh-host=0.0.0.0

bin/cobra ssh --ssh-user=ubuntu --ssh-host=0.0.0.0 --ssh-agent-private-keys=~/.ssh/id_rsa --ssh-agent-private-keys=~/.ssh/another
bin/cobra ssh --tmp-dir=/tmp/my-cobra --ssh-user=ubuntu --ssh-host=0.0.0.0 --use-agent-with-no-private-keys --force-no-private-keys

bin/cobra ssh-additional --ssh-user=ubuntu --kubeconfig=~/my.kind.kubeconfig
bin/cobra ssh --tmp-dir=/tmp/my-cobra --ssh-user=ubuntu --ssh-host=0.0.0.0 --use-standalone-kube --kubeconfig=~/my.kind.kubeconfig

SSH_HOST_CONNECT=0.0.0.0 bin/cobra ssh-additional --ssh-user=ubuntu
bin/cobra ssh --tmp-dir=/tmp/my-cobra --ssh-user=ubuntu --ssh-host=0.0.0.0 --ssh-agent-private-keys=~/.ssh/id_rsa --ssh-agent-private-keys=~/.ssh/another

SSH_HOST_CONNECT=0.0.0.0 bin/cobra ssh-additional --ssh-user=ubuntu --kubeconfig=~/kind.kubeconfig
bin/cobra ssh-additional --tmp-dir=/tmp/my-cobra --ssh-user=ubuntu --kubeconfig=~/my.kind.kubeconfig

SSH_HOST_CONNECT=0.0.0.0 bin/cobra --tmp-dir=/tmp/my-cobra ssh-additional --ssh-user=ubuntu

SSH_HOST_CONNECT=0.0.0.0 bin/cobra --tmp-dir=/tmp/my-cobra ssh-additional --ssh-user=ubuntu --kubeconfig=~/kind.kubeconfig
```
44 changes: 40 additions & 4 deletions examples/cobra/cmd/kube_only.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ package cmd

import (
"context"
"errors"
"fmt"
"time"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

connection "github.com/deckhouse/lib-connection/pkg"
"github.com/deckhouse/lib-connection/pkg/kube"
"github.com/deckhouse/lib-connection/pkg/provider"
Expand Down Expand Up @@ -105,7 +106,7 @@ func runKube(params *runKubeParams) error {
}

// default initialization way
initializer := provider.NewErrorSSHProviderForKubeInitializer(fmt.Errorf("should not use over ssh"))
initializer := provider.NewErrorSSHProviderInitializer(fmt.Errorf("should not use over ssh"))
runner, err := provider.GetRunnerInterface(ctx, conf, sett, initializer)
kubeProvider := provider.NewDefaultKubeProvider(sett, conf, runner)

Expand All @@ -121,19 +122,54 @@ func runKube(params *runKubeParams) error {
logger.InfoF("kube provider cleaned up successfully")
}()

logger := sett.Logger()

// example that additional flags also parsed
if *params.printWarn {
sett.Logger().WarnF("WARNING: printing warnings flag set")
logger.WarnF("WARNING: printing warnings flag set")
}

if err != nil {
return fmt.Errorf("failed to setup kube client", err)
return fmt.Errorf("failed to setup kube client: %w", err)
}

if err := getNodes(ctx, sett, kubeProvider); err != nil {
return fmt.Errorf("failed to get nodes: %w", err)
}

useSSHKubeConfig := &kube.Config{}

// example that returns error with SSHErrorProvider
runnerSSH, err := provider.GetRunnerInterface(ctx, useSSHKubeConfig, sett, initializer)
if err != nil {
return fmt.Errorf("cannot provide runner with ssh")
}

kubeErrProvider := provider.NewDefaultKubeProvider(sett, useSSHKubeConfig, runnerSSH)
_, err = kubeErrProvider.Client(ctx)
if err != nil {
if errors.Is(err, provider.ErrSSHClientCannotProvided) {
logger.InfoF("Cannot provide kube client because %v", err)
} else {
logger.ErrorF("Cannot provide kube client with unknown %v", err)
}
} else {
logger.ErrorF("Kube client should not provided")
}

// example fail fast with ProvideErrorSSHProviderInitializer
failFastInitializer := provider.NewProvideErrorSSHProviderInitializer(fmt.Errorf("should not use over ssh"))
_, err = provider.GetRunnerInterface(ctx, useSSHKubeConfig, sett, failFastInitializer)
if err != nil {
if errors.Is(err, provider.ErrCannotProvideSSHProvider) {
logger.InfoF("Cannot provide kube runner provider because %v", err)
} else {
logger.ErrorF("Cannot provide kube runner with unknown %v", err)
}
} else {
logger.ErrorF("Kube runner should not provided")
}

return nil
}

Expand Down
3 changes: 2 additions & 1 deletion examples/cobra/cmd/with_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -193,7 +194,7 @@ func doSSHCommand(ctx context.Context, sshClient connection.SSHClient) error {
return fmt.Errorf("failed to run echo command: %w", err)
}

if string(strOut) != echoStr {
if !strings.Contains(string(strOut), echoStr) {
return fmt.Errorf("failed to run echo command, got output: %s", string(strOut))
}

Expand Down
17 changes: 14 additions & 3 deletions examples/cobra/cmd/with_ssh_additional_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,15 @@ func runSSHAdditional(params *runSSHParams) error {
type providersConsumer interface {
provider.SSHProviderInitializerWithCleanup
provider.KubeProviderInitializerWithCleanup
SetSSHHost(h string)
}

func doSSHAdditional(ctx context.Context, sett settings.Settings, consumer providersConsumer) error {
hostFromEnv := os.Getenv("SSH_HOST_CONNECT")
if hostFromEnv != "" {
consumer.SetSSHHost(hostFromEnv)
}

kubeProvider, err := consumer.GetKubeProvider(ctx)
if err != nil {
return fmt.Errorf("Cannot initialize kube providder")
Expand Down Expand Up @@ -147,6 +153,8 @@ type additionalProvidersConsumer struct {

sshProvider connection.SSHProvider
kubeProvider connection.KubeProvider

sshHost string
}

func newAdditionalProvidersConsumer(params *runSSHParams, kubeConfig *kube.Config) *additionalProvidersConsumer {
Expand Down Expand Up @@ -186,13 +194,12 @@ func (i *additionalProvidersConsumer) GetSSHProvider(_ context.Context) (connect
}

if len(sshConfig.Hosts) == 0 {
hostFromEnv := os.Getenv("SSH_HOST_CONNECT")
if hostFromEnv == "" {
if i.sshHost == "" {
return nil, errNotPassedSSHHost
}

sshConfig.Hosts = append(sshConfig.Hosts, sshconfig.Host{
Host: hostFromEnv,
Host: i.sshHost,
})
}

Expand Down Expand Up @@ -226,3 +233,7 @@ func (i *additionalProvidersConsumer) Cleanup(ctx context.Context) error {

return nil
}

func (i *additionalProvidersConsumer) SetSSHHost(h string) {
i.sshHost = h
}
54 changes: 53 additions & 1 deletion pkg/provider/inititializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,36 @@ package provider

import (
"context"
"errors"
"fmt"

"github.com/name212/govalue"
"k8s.io/apimachinery/pkg/runtime/schema"

connection "github.com/deckhouse/lib-connection/pkg"
)

var (
_ SSHProviderInitializer = &SimpleSSHProviderInitializer{}
_ SSHProviderInitializerWithCleanup = &SimpleSSHProviderInitializer{}

_ SSHProviderInitializer = &ErrorSSHProviderInitializer{}
_ SSHProviderInitializerWithCleanup = &ErrorSSHProviderInitializer{}

_ SSHProviderInitializer = &ProvideErrorSSHProviderInitializer{}
_ SSHProviderInitializerWithCleanup = &ProvideErrorSSHProviderInitializer{}

_ KubeProviderInitializer = &SimpleKubeProviderInitializer{}
_ KubeProviderInitializerWithCleanup = &SimpleKubeProviderInitializer{}

_ KubeProviderInitializer = &FakeKubeProviderInitializer{}
_ KubeProviderInitializerWithCleanup = &FakeKubeProviderInitializer{}
)

var (
ErrCannotProvideSSHProvider = errors.New("cannot provide ssh provider initializer")
)

type SSHProviderInitializer interface {
GetSSHProvider(ctx context.Context) (connection.SSHProvider, error)
}
Expand Down Expand Up @@ -63,18 +86,47 @@ func (i *SimpleSSHProviderInitializer) Cleanup(ctx context.Context) error {
return i.provider.Cleanup(ctx)
}

// ErrorSSHProviderInitializer
// provide ErrorSSHProvider
// this provider returns error for every
// SSHProvider methods call
type ErrorSSHProviderInitializer struct {
*SimpleSSHProviderInitializer
}

func NewErrorSSHProviderForKubeInitializer(err error) *ErrorSSHProviderInitializer {
func NewErrorSSHProviderInitializer(err error) *ErrorSSHProviderInitializer {
return &ErrorSSHProviderInitializer{
SimpleSSHProviderInitializer: NewSimpleSSHProviderInitializer(
NewErrorSSHProvider(err),
),
}
}

// ProvideErrorSSHProviderInitializer
// this provider returns error for every GetSSHProvider call
// for fail fast in GetRunnerInterface func
type ProvideErrorSSHProviderInitializer struct {
err error
}

func NewProvideErrorSSHProviderInitializer(err error) *ProvideErrorSSHProviderInitializer {
if err == nil {
err = errors.New("unknown error")
}

return &ProvideErrorSSHProviderInitializer{
err: err,
}
}

func (i *ProvideErrorSSHProviderInitializer) GetSSHProvider(_ context.Context) (connection.SSHProvider, error) {
return nil, fmt.Errorf("%w: %w", ErrCannotProvideSSHProvider, i.err)
}

func (i *ProvideErrorSSHProviderInitializer) Cleanup(_ context.Context) error {
return nil
}

type SimpleKubeProviderInitializer struct {
provider connection.KubeProvider
}
Expand Down
7 changes: 5 additions & 2 deletions pkg/provider/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package provider

import (
"context"
"errors"
"fmt"
mathrand "math/rand"
"os"
Expand Down Expand Up @@ -700,14 +701,16 @@ type ErrorSSHProvider struct {
err error
}

var ErrSSHClientCannotProvided = errors.New("cannot provide ssh client")

// NewErrorSSHProvider
// Special provider that always return error for all operations
// expected cleanup
// it can be used with GetRunnerInterface if you are you sure that
// you do not use KubeClient over SSH
func NewErrorSSHProvider(err error) *ErrorSSHProvider {
if err == nil {
err = fmt.Errorf("ErrorSSHProvider: error not provided")
err = fmt.Errorf("%w ErrorSSHProvider: error not provided", ErrSSHClientCannotProvided)
}
return &ErrorSSHProvider{err: err}
}
Expand Down Expand Up @@ -737,5 +740,5 @@ func (p *ErrorSSHProvider) Cleanup(context.Context) error {
}

func (p *ErrorSSHProvider) returnError(op string) error {
return fmt.Errorf("cannot provide ssh client with %s: %w", op, p.err)
return fmt.Errorf("%w with %s: %w", ErrSSHClientCannotProvided, op, p.err)
}
1 change: 1 addition & 0 deletions pkg/ssh/clissh/cmd/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (s *SSH) Cmd(ctx context.Context) *exec.Cmd {
"-o", "ServerAliveInterval=1",
"-o", "ServerAliveCountMax=3600",
"-o", "ConnectTimeout=15",
"-o", "LogLevel=ERROR",
"-o", "PasswordAuthentication=no",
}

Expand Down
Loading
Loading