Skip to content

Commit

Permalink
e2e: add kubernetes interaction library
Browse files Browse the repository at this point in the history
Co-authored-by: Markus Rudy <[email protected]>
  • Loading branch information
msanft and burgerdev committed Feb 22, 2024
1 parent 6d25a1b commit 2f543e3
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 7 deletions.
117 changes: 117 additions & 0 deletions e2e/internal/kubeclient/kubeclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
The kubeclient package provides a simple wrapper around Kubernetes interactions
commonly used in the e2e tests.
*/
package kubeclient

import (
"bytes"
"context"
"fmt"
"log/slog"
"net/http"
"os"
"testing"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/remotecommand"
)

// A Kubeclient offers a communication interface to a Kubernetes cluster.
type Kubeclient struct {
log *slog.Logger

// client is the underlying Kubernetes client.
client *kubernetes.Clientset
// config is the "Kubeconfig" for the client
config *rest.Config
}

// New creates a new Kubeclient from a given Kubeconfig.
func New(config *rest.Config, log *slog.Logger) (*Kubeclient, error) {
client, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("creating kubernetes client: %w", err)
}

return &Kubeclient{
log: log,
client: client,
config: config,
}, nil
}

// NewFromConfigFile creates a new Kubeclient for a given Kubeconfig file.
func NewFromConfigFile(configPath string, log *slog.Logger) (*Kubeclient, error) {
config, err := clientcmd.BuildConfigFromFlags("", configPath)
if err != nil {
return nil, fmt.Errorf("creating config from file: %w", err)
}

return New(config, log)
}

// NewForTest creates a Kubeclient with parameters suitable for e2e testing.
func NewForTest(t *testing.T) *Kubeclient {
t.Helper()
log := slog.New(slog.NewTextHandler(os.Stderr, nil))
// TODO(burgerdev): consider reading KUBECONFIG env var
c, err := NewFromConfigFile(clientcmd.RecommendedHomeFile, log)
if err != nil {
t.Fatalf("Could not create Kubeclient: %v", err)
}
return c
}

// PodsFromDeployment returns the pods from a deployment in a namespace.
func (c *Kubeclient) PodsFromDeployment(ctx context.Context, namespace, deployment string) ([]v1.Pod, error) {
pods, err := c.client.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{
LabelSelector: fmt.Sprintf("app.kubernetes.io/name=%s", deployment),
})
if err != nil {
return nil, fmt.Errorf("listing pods: %w", err)
}

return pods.Items, nil
}

// Exec executes a process in a pod and returns the stdout and stderr.
func (c *Kubeclient) Exec(ctx context.Context, namespace, pod string, argv []string) (
stdout string, stderr string, err error,
) {
buf := &bytes.Buffer{}
errBuf := &bytes.Buffer{}
request := c.client.CoreV1().RESTClient().
Post().
Namespace(namespace).
Resource("pods").
Name(pod).
SubResource("exec").
VersionedParams(&v1.PodExecOptions{
Command: argv,
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
}, scheme.ParameterCodec)
exec, err := remotecommand.NewSPDYExecutor(c.config, http.MethodPost, request.URL())
if err != nil {
return "", "", fmt.Errorf("creating executor: %w", err)
}

err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{
Stdout: buf,
Stderr: errBuf,
Tty: false,
})
if err != nil {
return "", "", fmt.Errorf("executing command: %w", err)
}

return buf.String(), errBuf.String(), nil
}
22 changes: 20 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,54 @@ require (
google.golang.org/grpc v1.61.0
google.golang.org/protobuf v1.32.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.1
k8s.io/apimachinery v0.29.1
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/client-go v0.29.2
k8s.io/utils v0.0.0-20240102154912-e7106e64919e
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-configfs-tsm v0.2.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/logger v1.1.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
Expand Down
Loading

0 comments on commit 2f543e3

Please sign in to comment.