Skip to content

Commit

Permalink
helper functions for handling k8s objects
Browse files Browse the repository at this point in the history
  • Loading branch information
ShwethaKumbla committed Aug 23, 2021
1 parent 1a6ef66 commit 008f069
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 9 deletions.
19 changes: 10 additions & 9 deletions docs/design/klient-package.md
Expand Up @@ -536,15 +536,16 @@ func main() {
Name: podName,
}
}
pod2 := &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{{
Name: "nginx",
Image: imageutils.GetPauseImageName(),
}},
},
}
if err := res.Patch(context.TODO(), &pod1, &pod2); err != nil {
mergePatch, err := json.Marshal(map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"foo": "bar",
},
},
})
patch := k8s.Patch{PatchType: types.StrategicMergePatchType, Data: mergePatch}
if err := res.Patch(context.TODO(), &pod1, patch); err != nil {
log.Fatal("unable to update pod: ", err)
}
}
Expand Down
9 changes: 9 additions & 0 deletions klient/k8s/object.go
Expand Up @@ -19,6 +19,7 @@ package k8s
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
)

// Object is a union type that can represent either typed objects
Expand All @@ -35,3 +36,11 @@ type ObjectList interface {
metav1.ListInterface
runtime.Object
}

// Patch is a patch that can be applied to a Kubernetes object.
type Patch struct {
// PatchType is the type of the patch.
PatchType types.PatchType
// Data is the raw data representing the patch.
Data []byte
}
52 changes: 52 additions & 0 deletions klient/k8s/resources/resources.go
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"time"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
Expand All @@ -28,6 +29,7 @@ import (
"k8s.io/client-go/kubernetes/scheme"
cr "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/e2e-framework/klient/k8s"
"sigs.k8s.io/e2e-framework/utils"
)

type Resources struct {
Expand Down Expand Up @@ -109,6 +111,16 @@ func (r *Resources) Delete(ctx context.Context, obj k8s.Object, opts ...DeleteOp
return r.client.Delete(ctx, obj, o)
}

func WithGracePeriod(gpt time.Duration) DeleteOption {
t := gpt.Milliseconds()
return func(do *metav1.DeleteOptions) { do.GracePeriodSeconds = &t }
}

func WithDeletePropagation(prop string) DeleteOption {
p := metav1.DeletionPropagation(prop)
return func(do *metav1.DeleteOptions) { do.PropagationPolicy = &p }
}

type ListOption func(*metav1.ListOptions)

func (r *Resources) List(ctx context.Context, objs k8s.ObjectList, opts ...ListOption) error {
Expand All @@ -121,3 +133,43 @@ func (r *Resources) List(ctx context.Context, objs k8s.ObjectList, opts ...ListO
o := &cr.ListOptions{Raw: listOptions}
return r.client.List(ctx, objs, o)
}

func WithLabelSelector(sel string) ListOption {
return func(lo *metav1.ListOptions) { lo.LabelSelector = sel }
}

func WithFieldSelector(sel string) ListOption {
return func(lo *metav1.ListOptions) { lo.FieldSelector = sel }
}

func WithTimeout(to time.Duration) ListOption {
t := to.Milliseconds()
return func(lo *metav1.ListOptions) { lo.TimeoutSeconds = &t }
}

// PatchOption is used to provide additional arguments to the Patch call.
type PatchOption func(*metav1.PatchOptions)

// Patch patches portion of object `orig` with data from object `patch`
func (r *Resources) Patch(ctx context.Context, objs k8s.Object, patch k8s.Patch, opts ...PatchOption) error {
patchOptions := &metav1.PatchOptions{}

for _, fn := range opts {
fn(patchOptions)
}

p := cr.RawPatch(patch.PatchType, patch.Data)

o := &cr.PatchOptions{Raw: patchOptions}
return r.client.Patch(ctx, objs, p, o)
}

// Annotate attach annotations to an existing resource objec
func (r *Resources) Annotate(obj k8s.Object, annotation map[string]string) {
obj.SetAnnotations(annotation)
}

// Label apply labels to an existing resources.
func (r *Resources) Label(obj k8s.Object, label map[string]string) {
obj.SetLabels(label)
}
36 changes: 36 additions & 0 deletions klient/k8s/resources/resources_test.go
Expand Up @@ -18,13 +18,16 @@ package resources

import (
"context"
"encoding/json"
"fmt"
"testing"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
"sigs.k8s.io/e2e-framework/klient/k8s"
)

func TestCreate(t *testing.T) {
Expand Down Expand Up @@ -181,3 +184,36 @@ func TestList(t *testing.T) {
t.Error("there are no deployment exist", hasDep)
}
}

func TestPatch(t *testing.T) {
res, err := New(cfg)
if err != nil {
t.Errorf("config is nill")
}

mergePatch, err := json.Marshal(map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"ping": "pong",
},
},
})
if err != nil {
t.Error("error while json marshalling", err)
}

err = res.Patch(context.Background(), dep, k8s.Patch{PatchType: types.StrategicMergePatchType, Data: mergePatch})
if err != nil {
t.Error("error while patching the deployment", err)
}

obj := &appsv1.Deployment{}
err = res.Get(context.Background(), dep.Name, dep.Namespace, obj)
if err != nil {
t.Error("error while getting patched deployment", err)
}

if obj.Annotations["ping"] != "pong" {
t.Error("resource patch not applied correctly.")
}
}

0 comments on commit 008f069

Please sign in to comment.