Repository: kyverno/chainsaw
Pull request #86 (2023-10-17 07:01:51)

delete resource field

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/kyverno/chainsaw/pull/86?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) Report
> Merging [#86](https://app.codecov.io/gh/kyverno/chainsaw/pull/86?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) (904387b) into [main](https://app.codecov.io/gh/kyverno/chainsaw/commit/2c5d3531066af1870c0d943ee45dc1962c6666bb?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) (2c5d353) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##             main      #86   +/-   ##
=======================================
  Coverage   74.05%   74.05%           
=======================================
  Files           9        9           
  Lines         397      397           
=======================================
  Hits          294      294           
  Misses         72       72           
  Partials       31       31           
```



:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno)

shubham-cmyk: @eddycharly PTAL
shubham-cmyk: @eddycharly PTAL 
eddycharly: @shubham-cmyk conflict
shubham-cmyk: > @shubham-cmyk conflict

PTAL the conflict arise due to recently merged PR

Patch:
diff --git a/pkg/apis/v1alpha1/delete.go b/pkg/apis/v1alpha1/delete.go
new file mode 100644
index 00000000..98770d49
--- /dev/null
+++ b/pkg/apis/v1alpha1/delete.go
@@ -0,0 +1,13 @@
+package v1alpha1
+
+import corev1 "k8s.io/api/core/v1"
+
+// ObjectReference is a reference to an object that should be deleted
+type ObjectReference struct {
+	// Label selector to match objects to delete
+	// +optional
+	Labels map[string]string `json:"labels,omitempty"`
+	// Object reference to delete
+	// +optional
+	corev1.ObjectReference `json:",inline"`
+}
diff --git a/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/v1alpha1/zz_generated.deepcopy.go
index 52fef824..77cd7cef 100644
--- a/pkg/apis/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/v1alpha1/zz_generated.deepcopy.go
@@ -151,6 +151,30 @@ func (in *FileRef) DeepCopy() *FileRef {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ObjectReference) DeepCopyInto(out *ObjectReference) {
+	*out = *in
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	out.ObjectReference = in.ObjectReference
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReference.
+func (in *ObjectReference) DeepCopy() *ObjectReference {
+	if in == nil {
+		return nil
+	}
+	out := new(ObjectReference)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Test) DeepCopyInto(out *Test) {
 	*out = *in
@@ -246,6 +270,13 @@ func (in *TestStepSpec) DeepCopyInto(out *TestStepSpec) {
 		*out = make([]Error, len(*in))
 		copy(*out, *in)
 	}
+	if in.Delete != nil {
+		in, out := &in.Delete, &out.Delete
+		*out = make([]ObjectReference, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 	return
 }
 
diff --git a/pkg/client/delete.go b/pkg/client/delete.go
index c7245e88..f4c534f8 100644
--- a/pkg/client/delete.go
+++ b/pkg/client/delete.go
@@ -2,9 +2,14 @@ package client
 
 import (
 	"context"
+	"fmt"
+	"time"
 
+	"github.com/kyverno/chainsaw/pkg/apis/v1alpha1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/apimachinery/pkg/util/wait"
 	ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
@@ -30,3 +35,59 @@ func BlockingDelete(ctx context.Context, client Client, obj ctrlclient.Object) e
 	// TODO: context timeout
 	// return nil
 }
+
+func DeleteResource(ctx context.Context, client Client, delete *unstructured.Unstructured) error {
+	err := client.Delete(context.TODO(), delete)
+	if err != nil && !errors.IsNotFound(err) {
+		return err
+	}
+	// Wait for resources to be deleted.
+	return wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, 1*time.Second, true, wait.ConditionWithContextFunc(func(ctx context.Context) (bool, error) {
+		actual := &unstructured.Unstructured{}
+		actual.SetGroupVersionKind(delete.GetObjectKind().GroupVersionKind())
+		err = client.Get(context.TODO(), types.NamespacedName{Name: delete.GetName(), Namespace: delete.GetNamespace()}, actual)
+		if err == nil || !errors.IsNotFound(err) {
+			return false, err
+		}
+		return true, nil
+	}))
+}
+
+func NewResource(apiVersion, kind, name, namespace string) *unstructured.Unstructured {
+	meta := map[string]interface{}{}
+
+	if name != "" {
+		meta["name"] = name
+	}
+	if namespace != "" {
+		meta["namespace"] = namespace
+	}
+
+	return &unstructured.Unstructured{
+		Object: map[string]interface{}{
+			"apiVersion": apiVersion,
+			"kind":       kind,
+			"metadata":   meta,
+		},
+	}
+}
+
+func ListResourcesToDelete(c Client, delete v1alpha1.ObjectReference) (*unstructured.UnstructuredList, error) {
+	u := &unstructured.UnstructuredList{}
+	u.SetGroupVersionKind(delete.GetObjectKind().GroupVersionKind())
+
+	listOptions := []ctrlclient.ListOption{}
+	if delete.Labels != nil {
+		listOptions = append(listOptions, ctrlclient.MatchingLabels(delete.Labels))
+	}
+
+	if delete.Namespace != "" {
+		listOptions = append(listOptions, ctrlclient.InNamespace(delete.Namespace))
+	}
+
+	err := c.List(context.TODO(), u, listOptions...)
+	if err != nil {
+		return nil, fmt.Errorf("listing matching resources: %v", err)
+	}
+	return u, nil
+}
diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go
index 052b866e..956c47aa 100644
--- a/pkg/runner/runner.go
+++ b/pkg/runner/runner.go
@@ -146,6 +146,30 @@ func runTest(t *testing.T, ctx Context, test discovery.Test) {
 func executeStep(t *testing.T, logger logging.Logger, ctx Context, basePath string, step v1alpha1.TestStepSpec) {
 	t.Helper()
 	c := ctx.clientFactory(t, logger)
+
+	// Delete the Objects before the test step is executed
+	for _, delete := range step.Delete {
+		// Use your dynamic listing logic if the name is not provided
+		if delete.Name == "" {
+			u, err := client.ListResourcesToDelete(c, delete)
+			if err != nil {
+				t.Fatal(err)
+			}
+			for _, item := range u.Items {
+				currentItem := item
+				t.Logf("=== DELETE %s/%s", delete.APIVersion, delete.Kind)
+				if err := client.DeleteResource(context.TODO(), c, &currentItem); err != nil {
+					t.Fatal(err)
+				}
+			}
+		} else {
+			resource := client.NewResource(delete.APIVersion, delete.Kind, delete.Name, delete.Namespace)
+			t.Logf("=== DELETE %s/%s", delete.APIVersion, delete.Kind)
+			if err := client.DeleteResource(context.TODO(), c, resource); err != nil {
+				t.Fatal(err)
+			}
+		}
+	}
 	for _, apply := range step.Apply {
 		resources, err := resource.Load(filepath.Join(basePath, apply.File))
 		if err != nil {
diff --git a/website/docs/apis/chainsaw.v1alpha1.md b/website/docs/apis/chainsaw.v1alpha1.md
index 95aa4542..7778bf65 100644
--- a/website/docs/apis/chainsaw.v1alpha1.md
+++ b/website/docs/apis/chainsaw.v1alpha1.md
@@ -131,6 +131,20 @@ Instead of treating such an error as a test failure, it acknowledges it as expec
 |---|---|---|---|---|
 | `file` | `string` | :white_check_mark: |  | <p>File is the path to the referenced file.</p> |
 
+## `ObjectReference`     {#chainsaw-kyverno-io-v1alpha1-ObjectReference}
+
+**Appears in:**
+    
+- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+
+<p>ObjectReference is a reference to an object that should be deleted</p>
+
+
+| Field | Type | Required | Inline | Description |
+|---|---|---|---|---|
+| `labels` | `map[string]string` |  |  | <p>Label selector to match objects to delete</p> |
+| `ObjectReference` | [`core/v1.ObjectReference`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#objectreference-v1-core) |  | :white_check_mark: | <p>Object reference to delete</p> |
+
 ## `ReportFormatType`     {#chainsaw-kyverno-io-v1alpha1-ReportFormatType}
 
 (Alias of `string`)
@@ -167,5 +181,6 @@ Instead of treating such an error as a test failure, it acknowledges it as expec
 | `assert` | [`[]Assert`](#chainsaw-kyverno-io-v1alpha1-Assert) |  |  | <p>Assert represents the assertions to be made for this test step. It checks whether the conditions specified in each assertion hold true.</p> |
 | `apply` | [`[]Apply`](#chainsaw-kyverno-io-v1alpha1-Apply) |  |  | <p>Apply lists the resources that should be applied for this test step. This can include things like configuration settings or any other resources that need to be available during the test.</p> |
 | `error` | [`[]Error`](#chainsaw-kyverno-io-v1alpha1-Error) |  |  | <p>Error lists the expected errors for this test step. If any of these errors occur, the test will consider them as expected; otherwise, they will be treated as test failures.</p> |
+| `delete` | [`[]ObjectReference`](#chainsaw-kyverno-io-v1alpha1-ObjectReference) |  |  | <p>Delete provides a list of objects that should be deleted before this test step is executed. This helps in ensuring that the environment is set up correctly before the test step runs.</p> |
 
   
\ No newline at end of file


Test patch:
diff --git a/config/crds/chainsaw.kyverno.io_tests.yaml b/config/crds/chainsaw.kyverno.io_tests.yaml
index 1bf917e2..54ae00bf 100644
--- a/config/crds/chainsaw.kyverno.io_tests.yaml
+++ b/config/crds/chainsaw.kyverno.io_tests.yaml
@@ -71,6 +71,56 @@ spec:
                         - file
                         type: object
                       type: array
+                    delete:
+                      description: Delete provides a list of objects that should be
+                        deleted before this test step is executed. This helps in ensuring
+                        that the environment is set up correctly before the test step
+                        runs.
+                      items:
+                        description: ObjectReference is a reference to an object that
+                          should be deleted
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          fieldPath:
+                            description: 'If referring to a piece of an object instead
+                              of an entire object, this string should contain a valid
+                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                              For example, if the object reference is to a container
+                              within a pod, this would take on a value like: "spec.containers{name}"
+                              (where "name" refers to the name of the container that
+                              triggered the event) or if no container name is specified
+                              "spec.containers[2]" (container with index 2 in this
+                              pod). This syntax is chosen only to have some well-defined
+                              way of referencing a part of an object. TODO: this design
+                              is not final and this field is subject to change in
+                              the future.'
+                            type: string
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          labels:
+                            additionalProperties:
+                              type: string
+                            description: Label selector to match objects to delete
+                            type: object
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          resourceVersion:
+                            description: 'Specific resourceVersion to which this reference
+                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                            type: string
+                          uid:
+                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                            type: string
+                        type: object
+                        x-kubernetes-map-type: atomic
+                      type: array
                     error:
                       description: Error lists the expected errors for this test step.
                         If any of these errors occur, the test will consider them
diff --git a/config/crds/chainsaw.kyverno.io_teststeps.yaml b/config/crds/chainsaw.kyverno.io_teststeps.yaml
index 7b83d924..4fa086e5 100644
--- a/config/crds/chainsaw.kyverno.io_teststeps.yaml
+++ b/config/crds/chainsaw.kyverno.io_teststeps.yaml
@@ -65,6 +65,54 @@ spec:
                   - file
                   type: object
                 type: array
+              delete:
+                description: Delete provides a list of objects that should be deleted
+                  before this test step is executed. This helps in ensuring that the
+                  environment is set up correctly before the test step runs.
+                items:
+                  description: ObjectReference is a reference to an object that should
+                    be deleted
+                  properties:
+                    apiVersion:
+                      description: API version of the referent.
+                      type: string
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
+                    kind:
+                      description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                      type: string
+                    labels:
+                      additionalProperties:
+                        type: string
+                      description: Label selector to match objects to delete
+                      type: object
+                    name:
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                      type: string
+                    uid:
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                      type: string
+                  type: object
+                  x-kubernetes-map-type: atomic
+                type: array
               error:
                 description: Error lists the expected errors for this test step. If
                   any of these errors occur, the test will consider them as expected;
diff --git a/pkg/apis/v1alpha1/test_step_spec.go b/pkg/apis/v1alpha1/test_step_spec.go
index d2b5ee3b..53240eec 100644
--- a/pkg/apis/v1alpha1/test_step_spec.go
+++ b/pkg/apis/v1alpha1/test_step_spec.go
@@ -16,4 +16,9 @@ type TestStepSpec struct {
 	// will consider them as expected; otherwise, they will be treated as test failures.
 	// +optional
 	Error []Error `json:"error,omitempty"`
+
+	// Delete provides a list of objects that should be deleted before this test step is executed.
+	// This helps in ensuring that the environment is set up correctly before the test step runs.
+	// +optional
+	Delete []ObjectReference `json:"delete,omitempty"`
 }
diff --git a/pkg/data/crds/chainsaw.kyverno.io_tests.yaml b/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
index 1bf917e2..54ae00bf 100644
--- a/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
+++ b/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
@@ -71,6 +71,56 @@ spec:
                         - file
                         type: object
                       type: array
+                    delete:
+                      description: Delete provides a list of objects that should be
+                        deleted before this test step is executed. This helps in ensuring
+                        that the environment is set up correctly before the test step
+                        runs.
+                      items:
+                        description: ObjectReference is a reference to an object that
+                          should be deleted
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          fieldPath:
+                            description: 'If referring to a piece of an object instead
+                              of an entire object, this string should contain a valid
+                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                              For example, if the object reference is to a container
+                              within a pod, this would take on a value like: "spec.containers{name}"
+                              (where "name" refers to the name of the container that
+                              triggered the event) or if no container name is specified
+                              "spec.containers[2]" (container with index 2 in this
+                              pod). This syntax is chosen only to have some well-defined
+                              way of referencing a part of an object. TODO: this design
+                              is not final and this field is subject to change in
+                              the future.'
+                            type: string
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          labels:
+                            additionalProperties:
+                              type: string
+                            description: Label selector to match objects to delete
+                            type: object
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          resourceVersion:
+                            description: 'Specific resourceVersion to which this reference
+                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                            type: string
+                          uid:
+                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                            type: string
+                        type: object
+                        x-kubernetes-map-type: atomic
+                      type: array
                     error:
                       description: Error lists the expected errors for this test step.
                         If any of these errors occur, the test will consider them
diff --git a/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml b/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
index 7b83d924..4fa086e5 100644
--- a/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
+++ b/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
@@ -65,6 +65,54 @@ spec:
                   - file
                   type: object
                 type: array
+              delete:
+                description: Delete provides a list of objects that should be deleted
+                  before this test step is executed. This helps in ensuring that the
+                  environment is set up correctly before the test step runs.
+                items:
+                  description: ObjectReference is a reference to an object that should
+                    be deleted
+                  properties:
+                    apiVersion:
+                      description: API version of the referent.
+                      type: string
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
+                    kind:
+                      description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                      type: string
+                    labels:
+                      additionalProperties:
+                        type: string
+                      description: Label selector to match objects to delete
+                      type: object
+                    name:
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                      type: string
+                    uid:
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                      type: string
+                  type: object
+                  x-kubernetes-map-type: atomic
+                type: array
               error:
                 description: Error lists the expected errors for this test step. If
                   any of these errors occur, the test will consider them as expected;