From 8042b4f6a14eaac69af39ca858d9b323b91df1c9 Mon Sep 17 00:00:00 2001 From: Watson Sato Date: Fri, 26 Apr 2024 17:39:00 +0200 Subject: [PATCH] Don't fatal error when filter cannot iterate A jq filter may expect to iterate over a list of results, but it can happen that no result is returned. --- cmd/manager/scap.go | 8 ++++++++ cmd/manager/scap_test.go | 14 ++++++++++++++ tests/data/empty_machineconfig.json | 4 ++++ 3 files changed, 26 insertions(+) create mode 100644 tests/data/empty_machineconfig.json diff --git a/cmd/manager/scap.go b/cmd/manager/scap.go index 38e83f53e..886e061b1 100644 --- a/cmd/manager/scap.go +++ b/cmd/manager/scap.go @@ -52,6 +52,7 @@ const ( var ( MoreThanOneObjErr = errors.New("more than one object returned from the filter") + NullValErr = errors.New("no value was returned from the filter") ) // resourceFetcherClients just gathers several needed structs together so we can @@ -520,6 +521,8 @@ func fetch(ctx context.Context, streamDispatcher streamerDispatcherFn, rfClients filteredBody, filterErr := filter(ctx, body, rpath.Filter) if errors.Is(filterErr, MoreThanOneObjErr) { warnings = append(warnings, filterErr.Error()) + } else if errors.Is(filterErr, NullValErr) { + warnings = append(warnings, fmt.Sprintf("couldn't filter '%s': %s", body, filterErr.Error())) } else if filterErr != nil { return fmt.Errorf("couldn't filter '%s': %w", body, filterErr) } @@ -554,6 +557,11 @@ func filter(ctx context.Context, rawobj []byte, filter string) ([]byte, error) { } if err, ok := v.(error); ok { DBG("Error while filtering: %s", err) + // gojq may return a diverse set of internal errors caused by null values. + // These errors are happen when a piped filter ends up acting on a null value. + if strings.HasSuffix(err.Error(), ": null") { + return nil, fmt.Errorf("Skipping empty filter result from '%s': %w", filter, NullValErr) + } return nil, err } diff --git a/cmd/manager/scap_test.go b/cmd/manager/scap_test.go index a60a7e763..05ffe03bf 100644 --- a/cmd/manager/scap_test.go +++ b/cmd/manager/scap_test.go @@ -316,6 +316,20 @@ var _ = Describe("Testing filtering", func() { Expect(filterErr).Should(MatchError(MoreThanOneObjErr)) }) }) + Context("Piped Filtering", func() { + var rawmc []byte + BeforeEach(func() { + nsFile, err := os.Open("../../tests/data/empty_machineconfig.json") + Expect(err).To(BeNil()) + var readErr error + rawmc, readErr = io.ReadAll(nsFile) + Expect(readErr).To(BeNil()) + }) + It("skips filter piping errors", func() { + _, filterErr := filter(context.TODO(), rawmc, `[.items[] | select(.metadata.name | test("^rendered-worker-[0-9a-z]+$|^rendered-master-[0-9a-z]+$"))] | map(.spec.fips == true)`) + Expect(filterErr).Should(MatchError(NullValErr)) + }) + }) }) }) diff --git a/tests/data/empty_machineconfig.json b/tests/data/empty_machineconfig.json new file mode 100644 index 000000000..a7ecc1059 --- /dev/null +++ b/tests/data/empty_machineconfig.json @@ -0,0 +1,4 @@ +{ + "metadata": {}, + "items": null +}