Skip to content

Commit

Permalink
feat: add debug logs for helm (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
colesnodgrass authored Jul 23, 2024
1 parent 4b9dd0b commit 59f418e
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 46 deletions.
68 changes: 68 additions & 0 deletions internal/cmd/local/helm/helm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package helm

import (
"context"
"fmt"
"github.com/airbytehq/abctl/internal/cmd/local/localerr"
helmclient "github.com/mittwald/go-helm-client"
"github.com/pterm/pterm"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/repo"
"io"
"k8s.io/client-go/tools/clientcmd"
)

// Client primarily for testing purposes
type Client interface {
AddOrUpdateChartRepo(entry repo.Entry) error
GetChart(name string, options *action.ChartPathOptions) (*chart.Chart, string, error)
GetRelease(name string) (*release.Release, error)
InstallOrUpgradeChart(ctx context.Context, spec *helmclient.ChartSpec, opts *helmclient.GenericHelmOptions) (*release.Release, error)
UninstallReleaseByName(name string) error
}

// New returns the default helm client
func New(kubecfg, kubectx, namespace string) (Client, error) {
k8sCfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubecfg},
&clientcmd.ConfigOverrides{CurrentContext: kubectx},
)

restCfg, err := k8sCfg.ClientConfig()
if err != nil {
return nil, fmt.Errorf("%w: could not create rest config: %w", localerr.ErrKubernetes, err)
}

logger := helmLogger{}
helm, err := helmclient.NewClientFromRestConf(&helmclient.RestConfClientOptions{
Options: &helmclient.Options{
Namespace: namespace,
Output: logger,
DebugLog: logger.Debug,
Debug: true,
},
RestConfig: restCfg,
})
if err != nil {
return nil, fmt.Errorf("unable to create helm client: %w", err)
}

return helm, nil
}

var _ io.Writer = (*helmLogger)(nil)

// helmLogger is used by the Client to convert all helm output into debug logs.
type helmLogger struct {
}

func (d helmLogger) Write(p []byte) (int, error) {
pterm.Debug.Println(fmt.Sprintf("helm: %s", string(p)))
return len(p), nil
}

func (d helmLogger) Debug(format string, v ...interface{}) {
pterm.Debug.Println(fmt.Sprintf("helm - DEBUG: "+format, v...))
}
49 changes: 4 additions & 45 deletions internal/cmd/local/local/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/airbytehq/abctl/internal/cmd/local/docker"
"github.com/airbytehq/abctl/internal/cmd/local/helm"
"github.com/airbytehq/abctl/internal/cmd/local/migrate"
"github.com/airbytehq/abctl/internal/cmd/local/paths"
corev1 "k8s.io/api/core/v1"
Expand All @@ -24,8 +25,6 @@ import (
"github.com/pterm/pterm"
"golang.org/x/crypto/bcrypt"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/repo"
eventsv1 "k8s.io/api/events/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -53,15 +52,6 @@ const Port = 8000
// dockerAuthSecretName is the name of the secret which holds the docker authentication information.
const dockerAuthSecretName = "docker-auth"

// HelmClient primarily for testing purposes
type HelmClient interface {
AddOrUpdateChartRepo(entry repo.Entry) error
GetChart(string, *action.ChartPathOptions) (*chart.Chart, string, error)
GetRelease(name string) (*release.Release, error)
InstallOrUpgradeChart(ctx context.Context, spec *helmclient.ChartSpec, opts *helmclient.GenericHelmOptions) (*release.Release, error)
UninstallReleaseByName(string) error
}

type HTTPClient interface {
Do(req *http.Request) (*http.Response, error)
}
Expand All @@ -74,7 +64,7 @@ type Command struct {
provider k8s.Provider
cluster k8s.Cluster
http HTTPClient
helm HelmClient
helm helm.Client
k8s k8s.Client
portHTTP int
spinner *pterm.SpinnerPrinter
Expand All @@ -101,7 +91,7 @@ func WithHTTPClient(client HTTPClient) Option {
}

// WithHelmClient define the helm client for this command.
func WithHelmClient(client HelmClient) Option {
func WithHelmClient(client helm.Client) Option {
return func(c *Command) {
c.helm = client
}
Expand Down Expand Up @@ -172,7 +162,7 @@ func New(provider k8s.Provider, opts ...Option) (*Command, error) {
// set the helm client, if not defined
if c.helm == nil {
var err error
if c.helm, err = defaultHelm(provider.Kubeconfig, provider.Context); err != nil {
if c.helm, err = helm.New(provider.Kubeconfig, provider.Context, airbyteNamespace); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -765,41 +755,10 @@ func defaultK8s(kubecfg, kubectx string) (k8s.Client, error) {
return &k8s.DefaultK8sClient{ClientSet: k8sClient}, nil
}

// defaultHelm returns the default helm client
func defaultHelm(kubecfg, kubectx string) (HelmClient, error) {
k8sCfg, err := k8sClientConfig(kubecfg, kubectx)
if err != nil {
return nil, fmt.Errorf("%w: %w", localerr.ErrKubernetes, err)
}

restCfg, err := k8sCfg.ClientConfig()
if err != nil {
return nil, fmt.Errorf("%w: could not create rest config: %w", localerr.ErrKubernetes, err)
}

helm, err := helmclient.NewClientFromRestConf(&helmclient.RestConfClientOptions{
Options: &helmclient.Options{Namespace: airbyteNamespace, Output: &noopWriter{}, DebugLog: func(format string, v ...interface{}) {}},
RestConfig: restCfg,
})
if err != nil {
return nil, fmt.Errorf("unable to create helm client: %w", err)
}

return helm, nil
}

// k8sClientConfig returns a k8s client config using the ~/.kube/config file and the k8sContext context.
func k8sClientConfig(kubecfg, kubectx string) (clientcmd.ClientConfig, error) {
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubecfg},
&clientcmd.ConfigOverrides{CurrentContext: kubectx},
), nil
}

// noopWriter is used by the helm client to suppress its verbose output
type noopWriter struct {
}

func (w *noopWriter) Write(p []byte) (int, error) {
return len(p), nil
}
3 changes: 2 additions & 1 deletion internal/cmd/local/local/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/airbytehq/abctl/internal/cmd/local/helm"
"github.com/airbytehq/abctl/internal/cmd/local/k8s"
"github.com/airbytehq/abctl/internal/telemetry"
"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -338,7 +339,7 @@ func TestCommand_Install_InvalidValuesFile(t *testing.T) {
// ---
// only mocks below here
// ---
var _ HelmClient = (*mockHelmClient)(nil)
var _ helm.Client = (*mockHelmClient)(nil)

type mockHelmClient struct {
addOrUpdateChartRepo func(entry repo.Entry) error
Expand Down

0 comments on commit 59f418e

Please sign in to comment.