Repository: kyverno/chainsaw
Pull request #541 (2023-11-29 08:33:13)

feat: add inline assert and error support
Add inline assert and error support.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/kyverno/chainsaw/pull/541?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) Report
Attention: `18 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`47cb7b5`)](https://app.codecov.io/gh/kyverno/chainsaw/commit/47cb7b5839c20345199e96e45082de12d78a0255?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) 90.60% compared to head [(`c98679e`)](https://app.codecov.io/gh/kyverno/chainsaw/pull/541?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) 89.98%.

| [Files](https://app.codecov.io/gh/kyverno/chainsaw/pull/541?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) | Patch % | Lines |
|---|---|---|
| [pkg/commands/kuttl/migrate/command.go](https://app.codecov.io/gh/kyverno/chainsaw/pull/541?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno#diff-cGtnL2NvbW1hbmRzL2t1dHRsL21pZ3JhdGUvY29tbWFuZC5nbw==) | 0.00% | [18 Missing :warning: ](https://app.codecov.io/gh/kyverno/chainsaw/pull/541?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #541      +/-   ##
==========================================
- Coverage   90.60%   89.98%   -0.63%     
==========================================
  Files          74       74              
  Lines        2246     2266      +20     
==========================================
+ Hits         2035     2039       +4     
- Misses        150      166      +16     
  Partials       61       61              
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/kyverno/chainsaw/pull/541?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno).


Patch:
diff --git a/.release-notes/main.md b/.release-notes/main.md
index f51eb5fe..bd0d2f1f 100644
--- a/.release-notes/main.md
+++ b/.release-notes/main.md
@@ -22,6 +22,7 @@ Release notes for `TODO`.
 ## :dizzy: New features :dizzy:
 
 - Added support to register Chainsaw specific JMESPath functions for use in assertion trees
+- Added inline manifest support to `assert` and `error` operations
 
 ## :guitar: Misc :guitar:
 
diff --git a/pkg/apis/v1alpha1/apply.go b/pkg/apis/v1alpha1/apply.go
index 5c1c21ce..c69cb545 100644
--- a/pkg/apis/v1alpha1/apply.go
+++ b/pkg/apis/v1alpha1/apply.go
@@ -3,7 +3,7 @@ package v1alpha1
 // Apply represents a set of configurations or resources that
 // should be applied during testing.
 type Apply struct {
-	// FileRefOrResource provides a reference to the file containing the resources to be applied.
+	// FileRefOrResource provides a reference to the resources to be applied.
 	FileRefOrResource `json:",inline"`
 
 	// DryRun determines whether the file should be applied in dry run mode.
diff --git a/pkg/apis/v1alpha1/assert.go b/pkg/apis/v1alpha1/assert.go
index 13ac98cf..f28d391d 100644
--- a/pkg/apis/v1alpha1/assert.go
+++ b/pkg/apis/v1alpha1/assert.go
@@ -3,6 +3,6 @@ package v1alpha1
 // Assert represents a test condition that is expected to hold true
 // during the testing process.
 type Assert struct {
-	// FileRef provides a reference to the file containing the assertion.
-	FileRef `json:",inline"`
+	// FileRefOrResource provides a reference to the assertion.
+	FileRefOrResource `json:",inline"`
 }
diff --git a/pkg/apis/v1alpha1/error.go b/pkg/apis/v1alpha1/error.go
index 30edcd2f..daa36508 100644
--- a/pkg/apis/v1alpha1/error.go
+++ b/pkg/apis/v1alpha1/error.go
@@ -3,6 +3,6 @@ package v1alpha1
 // Error represents an anticipated error condition that may arise during testing.
 // Instead of treating such an error as a test failure, it acknowledges it as expected.
 type Error struct {
-	// FileRef provides a reference to the file containing the expected error.
-	FileRef `json:",inline"`
+	// FileRefOrResource provides a reference to the expected error.
+	FileRefOrResource `json:",inline"`
 }
diff --git a/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/v1alpha1/zz_generated.deepcopy.go
index 0ace7a77..108dbe3d 100644
--- a/pkg/apis/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/v1alpha1/zz_generated.deepcopy.go
@@ -58,7 +58,7 @@ func (in *Apply) DeepCopy() *Apply {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Assert) DeepCopyInto(out *Assert) {
 	*out = *in
-	out.FileRef = in.FileRef
+	in.FileRefOrResource.DeepCopyInto(&out.FileRefOrResource)
 	return
 }
 
@@ -258,7 +258,7 @@ func (in *Delete) DeepCopy() *Delete {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Error) DeepCopyInto(out *Error) {
 	*out = *in
-	out.FileRef = in.FileRef
+	in.FileRefOrResource.DeepCopyInto(&out.FileRefOrResource)
 	return
 }
 
@@ -448,7 +448,7 @@ func (in *Operation) DeepCopyInto(out *Operation) {
 	if in.Assert != nil {
 		in, out := &in.Assert, &out.Assert
 		*out = new(Assert)
-		**out = **in
+		(*in).DeepCopyInto(*out)
 	}
 	if in.Command != nil {
 		in, out := &in.Command, &out.Command
@@ -468,7 +468,7 @@ func (in *Operation) DeepCopyInto(out *Operation) {
 	if in.Error != nil {
 		in, out := &in.Error, &out.Error
 		*out = new(Error)
-		**out = **in
+		(*in).DeepCopyInto(*out)
 	}
 	if in.Script != nil {
 		in, out := &in.Script, &out.Script
diff --git a/pkg/commands/kuttl/migrate/command.go b/pkg/commands/kuttl/migrate/command.go
index e8b5777c..8fe3bbd3 100644
--- a/pkg/commands/kuttl/migrate/command.go
+++ b/pkg/commands/kuttl/migrate/command.go
@@ -240,10 +240,26 @@ func testStep(in unstructured.Unstructured) (*v1alpha1.TestStep, error) {
 		)
 	}
 	for _, operation := range from.Assert {
-		to.Spec.Try = append(to.Spec.Try, v1alpha1.Operation{Assert: &v1alpha1.Assert{FileRef: v1alpha1.FileRef{File: operation}}})
+		to.Spec.Try = append(to.Spec.Try, v1alpha1.Operation{
+			Assert: &v1alpha1.Assert{
+				FileRefOrResource: v1alpha1.FileRefOrResource{
+					FileRef: v1alpha1.FileRef{
+						File: operation,
+					},
+				},
+			},
+		})
 	}
 	for _, operation := range from.Error {
-		to.Spec.Try = append(to.Spec.Try, v1alpha1.Operation{Error: &v1alpha1.Error{FileRef: v1alpha1.FileRef{File: operation}}})
+		to.Spec.Try = append(to.Spec.Try, v1alpha1.Operation{
+			Error: &v1alpha1.Error{
+				FileRefOrResource: v1alpha1.FileRefOrResource{
+					FileRef: v1alpha1.FileRef{
+						File: operation,
+					},
+				},
+			},
+		})
 	}
 	for _, operation := range from.Delete {
 		to.Spec.Try = append(to.Spec.Try, v1alpha1.Operation{
diff --git a/pkg/discovery/load.go b/pkg/discovery/load.go
index 069b6aa4..0aa0d412 100644
--- a/pkg/discovery/load.go
+++ b/pkg/discovery/load.go
@@ -137,13 +137,17 @@ func LoadTest(fileName string, path string) (*Test, error) {
 				case "assert":
 					step.Spec.Try = append(step.Spec.Try, v1alpha1.Operation{
 						Assert: &v1alpha1.Assert{
-							FileRef: fileRef,
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: fileRef,
+							},
 						},
 					})
 				case "errors":
 					step.Spec.Try = append(step.Spec.Try, v1alpha1.Operation{
 						Error: &v1alpha1.Error{
-							FileRef: fileRef,
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: fileRef,
+							},
 						},
 					})
 				default:
diff --git a/pkg/runner/processors/step.go b/pkg/runner/processors/step.go
index 91f4f798..a340320e 100644
--- a/pkg/runner/processors/step.go
+++ b/pkg/runner/processors/step.go
@@ -260,7 +260,7 @@ func (p *stepProcessor) applyOperation(ctx context.Context, op v1alpha1.Apply, t
 }
 
 func (p *stepProcessor) assertOperation(ctx context.Context, op v1alpha1.Assert, to *metav1.Duration) ([]operation, error) {
-	resources, err := p.fileRef(op.FileRef)
+	resources, err := p.fileRefOrResource(op.FileRefOrResource)
 	if err != nil {
 		return nil, err
 	}
@@ -333,7 +333,7 @@ func (p *stepProcessor) deleteOperation(ctx context.Context, op v1alpha1.Delete,
 }
 
 func (p *stepProcessor) errorOperation(ctx context.Context, op v1alpha1.Error, to *metav1.Duration) ([]operation, error) {
-	resources, err := p.fileRef(op.FileRef)
+	resources, err := p.fileRefOrResource(op.FileRefOrResource)
 	if err != nil {
 		return nil, err
 	}
@@ -364,13 +364,6 @@ func (p *stepProcessor) scriptOperation(ctx context.Context, exec v1alpha1.Scrip
 	}
 }
 
-func (p *stepProcessor) fileRef(ref v1alpha1.FileRef) ([]unstructured.Unstructured, error) {
-	if ref.File != "" {
-		return resource.Load(filepath.Join(p.test.BasePath, ref.File))
-	}
-	return nil, errors.New("file must be set")
-}
-
 func (p *stepProcessor) fileRefOrResource(ref v1alpha1.FileRefOrResource) ([]unstructured.Unstructured, error) {
 	if ref.Resource != nil {
 		return []unstructured.Unstructured{*ref.Resource}, nil
diff --git a/pkg/validation/assert.go b/pkg/validation/assert.go
index 90d0b313..350662c8 100644
--- a/pkg/validation/assert.go
+++ b/pkg/validation/assert.go
@@ -8,7 +8,7 @@ import (
 func ValidateAssert(path *field.Path, obj *v1alpha1.Assert) field.ErrorList {
 	var errs field.ErrorList
 	if obj != nil {
-		errs = append(errs, ValidateFileRef(path, obj.FileRef)...)
+		errs = append(errs, ValidateFileRefOrResource(path, obj.FileRefOrResource)...)
 	}
 	return errs
 }
diff --git a/pkg/validation/error.go b/pkg/validation/error.go
index bc3c2413..c74171d9 100644
--- a/pkg/validation/error.go
+++ b/pkg/validation/error.go
@@ -8,7 +8,7 @@ import (
 func ValidateError(path *field.Path, obj *v1alpha1.Error) field.ErrorList {
 	var errs field.ErrorList
 	if obj != nil {
-		errs = append(errs, ValidateFileRef(path, obj.FileRef)...)
+		errs = append(errs, ValidateFileRefOrResource(path, obj.FileRefOrResource)...)
 	}
 	return errs
 }
diff --git a/website/docs/apis/chainsaw.v1alpha1.md b/website/docs/apis/chainsaw.v1alpha1.md
index 93083035..a8f33f0f 100644
--- a/website/docs/apis/chainsaw.v1alpha1.md
+++ b/website/docs/apis/chainsaw.v1alpha1.md
@@ -62,7 +62,7 @@ should be applied during testing.</p>
 
 | Field | Type | Required | Inline | Description |
 |---|---|---|---|---|
-| `FileRefOrResource` | [`FileRefOrResource`](#chainsaw-kyverno-io-v1alpha1-FileRefOrResource) | :white_check_mark: | :white_check_mark: | <p>FileRefOrResource provides a reference to the file containing the resources to be applied.</p> |
+| `FileRefOrResource` | [`FileRefOrResource`](#chainsaw-kyverno-io-v1alpha1-FileRefOrResource) | :white_check_mark: | :white_check_mark: | <p>FileRefOrResource provides a reference to the resources to be applied.</p> |
 | `dryRun` | `bool` |  |  | <p>DryRun determines whether the file should be applied in dry run mode.</p> |
 | `expect` | [`[]Expectation`](#chainsaw-kyverno-io-v1alpha1-Expectation) |  |  | <p>Expect defines a list of matched checks to validate the operation outcome.</p> |
 
@@ -78,7 +78,7 @@ during the testing process.</p>
 
 | Field | Type | Required | Inline | Description |
 |---|---|---|---|---|
-| `FileRef` | [`FileRef`](#chainsaw-kyverno-io-v1alpha1-FileRef) | :white_check_mark: | :white_check_mark: | <p>FileRef provides a reference to the file containing the assertion.</p> |
+| `FileRefOrResource` | [`FileRefOrResource`](#chainsaw-kyverno-io-v1alpha1-FileRefOrResource) | :white_check_mark: | :white_check_mark: | <p>FileRefOrResource provides a reference to the assertion.</p> |
 
 ## `Catch`     {#chainsaw-kyverno-io-v1alpha1-Catch}
 
@@ -183,7 +183,7 @@ Instead of treating such an error as a test failure, it acknowledges it as expec
 
 | Field | Type | Required | Inline | Description |
 |---|---|---|---|---|
-| `FileRef` | [`FileRef`](#chainsaw-kyverno-io-v1alpha1-FileRef) | :white_check_mark: | :white_check_mark: | <p>FileRef provides a reference to the file containing the expected error.</p> |
+| `FileRefOrResource` | [`FileRefOrResource`](#chainsaw-kyverno-io-v1alpha1-FileRefOrResource) | :white_check_mark: | :white_check_mark: | <p>FileRefOrResource provides a reference to the expected error.</p> |
 
 ## `Events`     {#chainsaw-kyverno-io-v1alpha1-Events}
 
@@ -222,8 +222,6 @@ with a match filter to determine if the verification should be considered.</p>
 
 **Appears in:**
     
-- [Assert](#chainsaw-kyverno-io-v1alpha1-Assert)
-- [Error](#chainsaw-kyverno-io-v1alpha1-Error)
 - [FileRefOrResource](#chainsaw-kyverno-io-v1alpha1-FileRefOrResource)
 
 <p>FileRef represents a file reference.</p>
@@ -238,7 +236,9 @@ with a match filter to determine if the verification should be considered.</p>
 **Appears in:**
     
 - [Apply](#chainsaw-kyverno-io-v1alpha1-Apply)
+- [Assert](#chainsaw-kyverno-io-v1alpha1-Assert)
 - [Create](#chainsaw-kyverno-io-v1alpha1-Create)
+- [Error](#chainsaw-kyverno-io-v1alpha1-Error)
 
 <p>FileRefOrResource represents a file reference or resource.</p>
 


Test patch:
diff --git a/.crds/chainsaw.kyverno.io_tests.yaml b/.crds/chainsaw.kyverno.io_tests.yaml
index 3b150899..9a493b99 100644
--- a/.crds/chainsaw.kyverno.io_tests.yaml
+++ b/.crds/chainsaw.kyverno.io_tests.yaml
@@ -334,6 +334,11 @@ spec:
                               file:
                                 description: File is the path to the referenced file.
                                 type: string
+                              resource:
+                                description: Resource provides a resource to be applied.
+                                type: object
+                                x-kubernetes-embedded-resource: true
+                                x-kubernetes-preserve-unknown-fields: true
                             type: object
                           command:
                             description: Command defines a command to run.
@@ -468,6 +473,11 @@ spec:
                               file:
                                 description: File is the path to the referenced file.
                                 type: string
+                              resource:
+                                description: Resource provides a resource to be applied.
+                                type: object
+                                x-kubernetes-embedded-resource: true
+                                x-kubernetes-preserve-unknown-fields: true
                             type: object
                           script:
                             description: Script defines a script to run.
diff --git a/.crds/chainsaw.kyverno.io_teststeps.yaml b/.crds/chainsaw.kyverno.io_teststeps.yaml
index 0d03aaf9..cfd81938 100644
--- a/.crds/chainsaw.kyverno.io_teststeps.yaml
+++ b/.crds/chainsaw.kyverno.io_teststeps.yaml
@@ -292,6 +292,11 @@ spec:
                         file:
                           description: File is the path to the referenced file.
                           type: string
+                        resource:
+                          description: Resource provides a resource to be applied.
+                          type: object
+                          x-kubernetes-embedded-resource: true
+                          x-kubernetes-preserve-unknown-fields: true
                       type: object
                     command:
                       description: Command defines a command to run.
@@ -418,6 +423,11 @@ spec:
                         file:
                           description: File is the path to the referenced file.
                           type: string
+                        resource:
+                          description: Resource provides a resource to be applied.
+                          type: object
+                          x-kubernetes-embedded-resource: true
+                          x-kubernetes-preserve-unknown-fields: true
                       type: object
                     script:
                       description: Script defines a script to run.
diff --git a/pkg/data/crds/chainsaw.kyverno.io_tests.yaml b/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
index 3b150899..9a493b99 100644
--- a/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
+++ b/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
@@ -334,6 +334,11 @@ spec:
                               file:
                                 description: File is the path to the referenced file.
                                 type: string
+                              resource:
+                                description: Resource provides a resource to be applied.
+                                type: object
+                                x-kubernetes-embedded-resource: true
+                                x-kubernetes-preserve-unknown-fields: true
                             type: object
                           command:
                             description: Command defines a command to run.
@@ -468,6 +473,11 @@ spec:
                               file:
                                 description: File is the path to the referenced file.
                                 type: string
+                              resource:
+                                description: Resource provides a resource to be applied.
+                                type: object
+                                x-kubernetes-embedded-resource: true
+                                x-kubernetes-preserve-unknown-fields: true
                             type: object
                           script:
                             description: Script defines a script to run.
diff --git a/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml b/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
index 0d03aaf9..cfd81938 100644
--- a/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
+++ b/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
@@ -292,6 +292,11 @@ spec:
                         file:
                           description: File is the path to the referenced file.
                           type: string
+                        resource:
+                          description: Resource provides a resource to be applied.
+                          type: object
+                          x-kubernetes-embedded-resource: true
+                          x-kubernetes-preserve-unknown-fields: true
                       type: object
                     command:
                       description: Command defines a command to run.
@@ -418,6 +423,11 @@ spec:
                         file:
                           description: File is the path to the referenced file.
                           type: string
+                        resource:
+                          description: Resource provides a resource to be applied.
+                          type: object
+                          x-kubernetes-embedded-resource: true
+                          x-kubernetes-preserve-unknown-fields: true
                       type: object
                     script:
                       description: Script defines a script to run.
diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go
index c343d1eb..856bfc0c 100644
--- a/pkg/discovery/discovery_test.go
+++ b/pkg/discovery/discovery_test.go
@@ -50,8 +50,10 @@ func TestDiscoverTests(t *testing.T) {
 						Spec: v1alpha1.TestStepSpec{
 							Try: []v1alpha1.Operation{{
 								Assert: &v1alpha1.Assert{
-									FileRef: v1alpha1.FileRef{
-										File: "configmap.yaml",
+									FileRefOrResource: v1alpha1.FileRefOrResource{
+										FileRef: v1alpha1.FileRef{
+											File: "configmap.yaml",
+										},
 									},
 								},
 							}},
@@ -89,14 +91,18 @@ func TestDiscoverTests(t *testing.T) {
 								},
 							}, {
 								Assert: &v1alpha1.Assert{
-									FileRef: v1alpha1.FileRef{
-										File: "01-assert.yaml",
+									FileRefOrResource: v1alpha1.FileRefOrResource{
+										FileRef: v1alpha1.FileRef{
+											File: "01-assert.yaml",
+										},
 									},
 								},
 							}, {
 								Error: &v1alpha1.Error{
-									FileRef: v1alpha1.FileRef{
-										File: "01-errors.yaml",
+									FileRefOrResource: v1alpha1.FileRefOrResource{
+										FileRef: v1alpha1.FileRef{
+											File: "01-errors.yaml",
+										},
 									},
 								},
 							}},
@@ -134,8 +140,10 @@ func TestDiscoverTests(t *testing.T) {
 								},
 							}, {
 								Assert: &v1alpha1.Assert{
-									FileRef: v1alpha1.FileRef{
-										File: "bar.yaml",
+									FileRefOrResource: v1alpha1.FileRefOrResource{
+										FileRef: v1alpha1.FileRef{
+											File: "bar.yaml",
+										},
 									},
 								},
 							}},
diff --git a/pkg/discovery/load_test.go b/pkg/discovery/load_test.go
index 6ed7b877..8b767722 100644
--- a/pkg/discovery/load_test.go
+++ b/pkg/discovery/load_test.go
@@ -69,8 +69,10 @@ func TestLoadTest(t *testing.T) {
 							Spec: v1alpha1.TestStepSpec{
 								Try: []v1alpha1.Operation{{
 									Assert: &v1alpha1.Assert{
-										FileRef: v1alpha1.FileRef{
-											File: "configmap.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
 										},
 									},
 								}},
@@ -117,8 +119,10 @@ func TestLoadTest(t *testing.T) {
 								Try: []v1alpha1.Operation{
 									{
 										Assert: &v1alpha1.Assert{
-											FileRef: v1alpha1.FileRef{
-												File: "configmap.yaml",
+											FileRefOrResource: v1alpha1.FileRefOrResource{
+												FileRef: v1alpha1.FileRef{
+													File: "configmap.yaml",
+												},
 											},
 										},
 									},
@@ -160,8 +164,10 @@ func TestLoadTest(t *testing.T) {
 									},
 								}, {
 									Assert: &v1alpha1.Assert{
-										FileRef: v1alpha1.FileRef{
-											File: "bar.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
 										},
 									},
 								}},
@@ -200,8 +206,10 @@ func TestLoadTest(t *testing.T) {
 									},
 								}, {
 									Assert: &v1alpha1.Assert{
-										FileRef: v1alpha1.FileRef{
-											File: "bar.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
 										},
 									},
 								}},
@@ -240,8 +248,10 @@ func TestLoadTest(t *testing.T) {
 									},
 								}, {
 									Assert: &v1alpha1.Assert{
-										FileRef: v1alpha1.FileRef{
-											File: "bar.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
 										},
 									},
 								}, {
@@ -254,14 +264,18 @@ func TestLoadTest(t *testing.T) {
 									},
 								}, {
 									Assert: &v1alpha1.Assert{
-										FileRef: v1alpha1.FileRef{
-											File: "01-assert.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "01-assert.yaml",
+											},
 										},
 									},
 								}, {
 									Error: &v1alpha1.Error{
-										FileRef: v1alpha1.FileRef{
-											File: "01-errors.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "01-errors.yaml",
+											},
 										},
 									},
 								}},
@@ -300,14 +314,18 @@ func TestLoadTest(t *testing.T) {
 									},
 								}, {
 									Assert: &v1alpha1.Assert{
-										FileRef: v1alpha1.FileRef{
-											File: "01-assert.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "01-assert.yaml",
+											},
 										},
 									},
 								}, {
 									Error: &v1alpha1.Error{
-										FileRef: v1alpha1.FileRef{
-											File: "01-errors.yaml",
+										FileRefOrResource: v1alpha1.FileRefOrResource{
+											FileRef: v1alpha1.FileRef{
+												File: "01-errors.yaml",
+											},
 										},
 									},
 								}},
diff --git a/pkg/step/load_test.go b/pkg/step/load_test.go
index 0ba7ca06..15664f66 100644
--- a/pkg/step/load_test.go
+++ b/pkg/step/load_test.go
@@ -73,8 +73,10 @@ func TestLoad(t *testing.T) {
 						},
 					}, {
 						Assert: &v1alpha1.Assert{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: v1alpha1.FileRef{
+									File: "bar.yaml",
+								},
 							},
 						},
 					}},
@@ -104,8 +106,10 @@ func TestLoad(t *testing.T) {
 						},
 					}, {
 						Assert: &v1alpha1.Assert{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: v1alpha1.FileRef{
+									File: "bar.yaml",
+								},
 							},
 						},
 					}},
@@ -154,8 +158,10 @@ func TestLoad(t *testing.T) {
 						},
 					}, {
 						Assert: &v1alpha1.Assert{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: v1alpha1.FileRef{
+									File: "bar.yaml",
+								},
 							},
 						},
 					}},
@@ -204,8 +210,10 @@ func TestLoad(t *testing.T) {
 						},
 					}, {
 						Assert: &v1alpha1.Assert{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: v1alpha1.FileRef{
+									File: "bar.yaml",
+								},
 							},
 						},
 					}},
@@ -230,8 +238,10 @@ func TestLoad(t *testing.T) {
 						},
 					}, {
 						Assert: &v1alpha1.Assert{
-							FileRef: v1alpha1.FileRef{
-								File: "foo.yaml",
+							FileRefOrResource: v1alpha1.FileRefOrResource{
+								FileRef: v1alpha1.FileRef{
+									File: "foo.yaml",
+								},
 							},
 						},
 					}},
diff --git a/pkg/test/load_test.go b/pkg/test/load_test.go
index 488572ce..bda1a098 100644
--- a/pkg/test/load_test.go
+++ b/pkg/test/load_test.go
@@ -101,8 +101,10 @@ func TestLoad(t *testing.T) {
 					Spec: v1alpha1.TestStepSpec{
 						Try: []v1alpha1.Operation{{
 							Assert: &v1alpha1.Assert{
-								FileRef: v1alpha1.FileRef{
-									File: "bar.yaml",
+								FileRefOrResource: v1alpha1.FileRefOrResource{
+									FileRef: v1alpha1.FileRef{
+										File: "bar.yaml",
+									},
 								},
 							},
 						}},
diff --git a/pkg/validation/operation_test.go b/pkg/validation/operation_test.go
index 12a004a6..fe0e49ab 100644
--- a/pkg/validation/operation_test.go
+++ b/pkg/validation/operation_test.go
@@ -18,8 +18,10 @@ func TestValidateOperation(t *testing.T) {
 		},
 	}
 	exampleAssert := &v1alpha1.Assert{
-		FileRef: v1alpha1.FileRef{
-			File: "example.yaml",
+		FileRefOrResource: v1alpha1.FileRefOrResource{
+			FileRef: v1alpha1.FileRef{
+				File: "example.yaml",
+			},
 		},
 	}
 	exampleCommand := &v1alpha1.Command{
@@ -46,87 +48,77 @@ func TestValidateOperation(t *testing.T) {
 		},
 	}
 	exampleError := &v1alpha1.Error{
-		FileRef: v1alpha1.FileRef{
-			File: "example.yaml",
+		FileRefOrResource: v1alpha1.FileRefOrResource{
+			FileRef: v1alpha1.FileRef{
+				File: "example.yaml",
+			},
 		},
 	}
 	exampleScript := &v1alpha1.Script{
 		Content: "echo 'hello world'",
 	}
-
 	tests := []struct {
 		name      string
 		input     v1alpha1.Operation
 		expectErr bool
 		errMsg    string
-	}{
-		{
-			name:      "No operation statements provided",
-			input:     v1alpha1.Operation{},
-			expectErr: true,
-			errMsg:    "no statement found in operation",
-		},
-		{
-			name: "Multiple operation statements provided",
-			input: v1alpha1.Operation{
-				Apply:   exampleApply,
-				Assert:  exampleAssert,
-				Command: exampleCommand,
-			},
-			expectErr: true,
-			errMsg:    fmt.Sprintf("only one statement is allowed per operation (found %d)", 3),
+	}{{
+		name:      "No operation statements provided",
+		input:     v1alpha1.Operation{},
+		expectErr: true,
+		errMsg:    "no statement found in operation",
+	}, {
+		name: "Multiple operation statements provided",
+		input: v1alpha1.Operation{
+			Apply:   exampleApply,
+			Assert:  exampleAssert,
+			Command: exampleCommand,
 		},
-		{
-			name: "Only Apply operation statement provided",
-			input: v1alpha1.Operation{
-				Apply: exampleApply,
-			},
-			expectErr: false,
+		expectErr: true,
+		errMsg:    fmt.Sprintf("only one statement is allowed per operation (found %d)", 3),
+	}, {
+		name: "Only Apply operation statement provided",
+		input: v1alpha1.Operation{
+			Apply: exampleApply,
 		},
-		{
-			name: "Only Assert operation statement provided",
-			input: v1alpha1.Operation{
-				Assert: exampleAssert,
-			},
-			expectErr: false,
+		expectErr: false,
+	}, {
+		name: "Only Assert operation statement provided",
+		input: v1alpha1.Operation{
+			Assert: exampleAssert,
 		},
-		{
-			name: "Only Command operation statement provided",
-			input: v1alpha1.Operation{
-				Command: exampleCommand,
-			},
-			expectErr: false,
+		expectErr: false,
+	}, {
+		name: "Only Command operation statement provided",
+		input: v1alpha1.Operation{
+			Command: exampleCommand,
 		},
-		{
-			name: "Only Create operation statement provided",
-			input: v1alpha1.Operation{
-				Create: exampleCreate,
-			},
-			expectErr: false,
+		expectErr: false,
+	}, {
+		name: "Only Create operation statement provided",
+		input: v1alpha1.Operation{
+			Create: exampleCreate,
 		},
-		{
-			name: "Only Delete operation statement provided",
-			input: v1alpha1.Operation{
-				Delete: exampleDelete,
-			},
-			expectErr: false,
+		expectErr: false,
+	}, {
+		name: "Only Delete operation statement provided",
+		input: v1alpha1.Operation{
+			Delete: exampleDelete,
 		},
-		{
-			name: "Only Error operation statement provided",
-			input: v1alpha1.Operation{
-				Error: exampleError,
-			},
-			expectErr: false,
+		expectErr: false,
+	}, {
+		name: "Only Error operation statement provided",
+		input: v1alpha1.Operation{
+			Error: exampleError,
 		},
-		{
-			name: "Only Script operation statement provided",
-			input: v1alpha1.Operation{
-				Script: exampleScript,
-			},
-			expectErr: false,
+		expectErr: false,
+	}, {
+		name: "Only Script operation statement provided",
+		input: v1alpha1.Operation{
+			Script: exampleScript,
 		},
-	}
-
+		expectErr: false,
+	}}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			errs := ValidateOperation(field.NewPath("testPath"), tt.input)
diff --git a/pkg/validation/test_step_spec_test.go b/pkg/validation/test_step_spec_test.go
index c06e91cc..e05a2bd6 100644
--- a/pkg/validation/test_step_spec_test.go
+++ b/pkg/validation/test_step_spec_test.go
@@ -28,8 +28,10 @@ func TestValidateTestStepSpec(t *testing.T) {
 				},
 			},
 			Assert: &v1alpha1.Assert{
-				FileRef: v1alpha1.FileRef{
-					File: "file",
+				FileRefOrResource: v1alpha1.FileRefOrResource{
+					FileRef: v1alpha1.FileRef{
+						File: "file",
+					},
 				},
 			},
 		},
diff --git a/pkg/validation/test_step_test.go b/pkg/validation/test_step_test.go
index 48019563..7a99d330 100644
--- a/pkg/validation/test_step_test.go
+++ b/pkg/validation/test_step_test.go
@@ -32,35 +32,32 @@ func TestValidateTestStep(t *testing.T) {
 					},
 				},
 				Assert: &v1alpha1.Assert{
-					FileRef: v1alpha1.FileRef{
-						File: "file",
+					FileRefOrResource: v1alpha1.FileRefOrResource{
+						FileRef: v1alpha1.FileRef{
+							File: "file",
+						},
 					},
 				},
 			},
 		},
 	}
-
 	tests := []struct {
 		name      string
 		input     *v1alpha1.TestStep
 		expectErr bool
-	}{
-		{
-			name: "Valid TestStepSpec",
-			input: &v1alpha1.TestStep{
-				Spec: validTestStepSpec,
-			},
-			expectErr: false,
+	}{{
+		name: "Valid TestStepSpec",
+		input: &v1alpha1.TestStep{
+			Spec: validTestStepSpec,
 		},
-		{
-			name: "Invalid TestStepSpec",
-			input: &v1alpha1.TestStep{
-				Spec: invalidTestStepSpec,
-			},
-			expectErr: true,
+		expectErr: false,
+	}, {
+		name: "Invalid TestStepSpec",
+		input: &v1alpha1.TestStep{
+			Spec: invalidTestStepSpec,
 		},
-	}
-
+		expectErr: true,
+	}}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			errs := ValidateTestStep(tt.input)
diff --git a/pkg/validation/test_test.go b/pkg/validation/test_test.go
index 392c8ae9..6ec5fd63 100644
--- a/pkg/validation/test_test.go
+++ b/pkg/validation/test_test.go
@@ -43,8 +43,10 @@ func TestValidateTest(t *testing.T) {
 								},
 							},
 							Assert: &v1alpha1.Assert{
-								FileRef: v1alpha1.FileRef{
-									File: "file",
+								FileRefOrResource: v1alpha1.FileRefOrResource{
+									FileRef: v1alpha1.FileRef{
+										File: "file",
+									},
 								},
 							},
 						},
diff --git a/testdata/e2e/quick-start/inline/chainsaw-test.yaml b/testdata/e2e/quick-start/inline/chainsaw-test.yaml
index 73697989..53f1038a 100644
--- a/testdata/e2e/quick-start/inline/chainsaw-test.yaml
+++ b/testdata/e2e/quick-start/inline/chainsaw-test.yaml
@@ -14,4 +14,10 @@ spec:
           data:
             foo: bar
     - assert:
-        file: configmap-assert.yaml
+        resource:
+          apiVersion: v1
+          kind: ConfigMap
+          metadata:
+            name: quick-start
+          data:
+            foo: bar
diff --git a/testdata/e2e/quick-start/inline/configmap-assert.yaml b/testdata/e2e/quick-start/inline/configmap-assert.yaml
deleted file mode 100644
index 07a440b5..00000000
--- a/testdata/e2e/quick-start/inline/configmap-assert.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
-  name: quick-start
-data:
-  foo: bar