From ca2c610e997081a309ca1dfa05e757dc218aa05b Mon Sep 17 00:00:00 2001 From: Justin Griffin Date: Wed, 13 Apr 2022 12:25:29 -0400 Subject: [PATCH] Add `youngerThan` filter (#33) Added support for filtering by creation timestamp that is `youngerThan` a specified amount of time. ```yaml source: filter: youngerThan: 3600 ``` This inversely complements the existing filter functionality for `olderThan`, and can also be used together to define a time window. For example, resources created between 1 and 2 hours ago: ```yaml source: filter: olderThan: 3600 youngerThan: 7200 ``` Signed-off-by: Justin Griffin --- README.adoc | 9 ++ assets/query | 12 ++ test/check.bats | 104 ++++++++++++++++++ ...n-source-filter-youngerThan-olderThan.json | 8 ++ .../stdin-source-filter-youngerThan.json | 7 ++ 5 files changed, 140 insertions(+) create mode 100644 test/fixtures/stdin-source-filter-youngerThan-olderThan.json create mode 100644 test/fixtures/stdin-source-filter-youngerThan.json diff --git a/README.adoc b/README.adoc index 629e8e9..c887521 100644 --- a/README.adoc +++ b/README.adoc @@ -77,6 +77,15 @@ source: olderThan: 86400 ---- +** `youngerThan`: Time in seconds that the `metadata.creationTimestamp` must be younger than (ex: `3600` for 1hr). ++ +[source,yaml] +---- +source: + filter: + youngerThan: 3600 +---- + ** `phases`: List of `status.phase` value(s) the resource must match at least one of. This varies depending on the resource. For example, a https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase[pod's status] can be one of `Pending`, `Running`, `Succeeded`, `Failed` or `Unknown`. To retrieve only `Failed` or `Unknown` pods: diff --git a/assets/query b/assets/query index bc327f6..8730abd 100755 --- a/assets/query +++ b/assets/query @@ -7,6 +7,7 @@ queryAndFilter() { queryForVersions filterByName filterByCreationOlderThan + filterByCreationYoungerThan filterByPhases filterByJQExpressions } @@ -44,6 +45,17 @@ filterByCreationOlderThan() { fi } +filterByCreationYoungerThan() { + local filter_younger_than=$(jq -r '.source.filter.youngerThan // ""' < $payload) + if [ ! -z "$filter_younger_than" ]; then + log -p "--> filtering by creation timestamp younger than: ${cyan}$filter_younger_than${reset}" + new_versions=$(echo $new_versions | tr '\r\n' ' ' | jq --argjson MIN_AGE $(( $(date +%s) - $filter_younger_than)) -r '[.[] | select(.metadata.creationTimestamp | fromdate | tonumber | select(. > $MIN_AGE)) ]') + log "$new_versions" + else + log "--> creation timestamp (younger than) filter not configured, skipping...." + fi +} + filterByPhases() { local filter_phases=$(jq -r '.source.filter.phases // ""' < $payload) if [ ! -z "$filter_phases" ]; then diff --git a/test/check.bats b/test/check.bats index dc9be2f..b16187b 100644 --- a/test/check.bats +++ b/test/check.bats @@ -223,6 +223,110 @@ teardown() { assert_equal "$(jq -r '.[2].metadata.name' <<< "$new_versions")" 'namespace-3' } +@test "[check] filter by youngerThan" { + source_check "stdin-source-filter-youngerThan" + + now="$(date +%Y-%m-%dT%H:%M:%SZ)" + hourAgo="$(date -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)" + dayAgo="$(date -d '25 hours ago' +%Y-%m-%dT%H:%M:%SZ)" + + new_versions="[ + { + \"metadata\": { + \"name\": \"namespace-1\", + \"creationTimestamp\": \"$now\" + } + }, + { + \"metadata\": { + \"name\": \"namespace-2\", + \"creationTimestamp\": \"$hourAgo\" + } + }, + { + \"metadata\": { + \"name\": \"namespace-3\", + \"creationTimestamp\": \"$dayAgo\" + } + } + ]" + + filterByCreationYoungerThan + + # then we only have namespaces younger than our criteria (1 hour) + assert_equal $(jq length <<< "$new_versions") 1 + assert_equal "$(jq -r '.[0].metadata.name' <<< "$new_versions")" 'namespace-1' +} + +@test "[check] filter by youngerThan not configured" { + source_check "stdin-source-empty" + + new_versions="[ + { + \"metadata\": { + \"name\": \"namespace-1\", + \"creationTimestamp\": \"$now\" + } + }, + { + \"metadata\": { + \"name\": \"namespace-2\", + \"creationTimestamp\": \"$hourAgo\" + } + }, + { + \"metadata\": { + \"name\": \"namespace-3\", + \"creationTimestamp\": \"$dayAgo\" + } + } + ]" + + filterByCreationYoungerThan + + # then our 'new_versions' is left unchanged + assert_equal $(jq length <<< "$new_versions") 3 + assert_equal "$(jq -r '.[0].metadata.name' <<< "$new_versions")" 'namespace-1' + assert_equal "$(jq -r '.[1].metadata.name' <<< "$new_versions")" 'namespace-2' + assert_equal "$(jq -r '.[2].metadata.name' <<< "$new_versions")" 'namespace-3' +} + +@test "[check] filter by youngerThan and olderThan (together)" { + source_check "stdin-source-filter-youngerThan-olderThan" + + now="$(date +%Y-%m-%dT%H:%M:%SZ)" + hourAgo="$(date -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)" + dayAgo="$(date -d '25 hours ago' +%Y-%m-%dT%H:%M:%SZ)" + + new_versions="[ + { + \"metadata\": { + \"name\": \"namespace-1\", + \"creationTimestamp\": \"$now\" + } + }, + { + \"metadata\": { + \"name\": \"namespace-2\", + \"creationTimestamp\": \"$hourAgo\" + } + }, + { + \"metadata\": { + \"name\": \"namespace-3\", + \"creationTimestamp\": \"$dayAgo\" + } + } + ]" + + filterByCreationOlderThan + filterByCreationYoungerThan + + # then we only have namespaces that fit between our age range + assert_equal $(jq length <<< "$new_versions") 1 + assert_equal "$(jq -r '.[0].metadata.name' <<< "$new_versions")" 'namespace-2' +} + @test "[check] pare down version info and emit only uid/resourceVersion" { source_check diff --git a/test/fixtures/stdin-source-filter-youngerThan-olderThan.json b/test/fixtures/stdin-source-filter-youngerThan-olderThan.json new file mode 100644 index 0000000..e9d87e0 --- /dev/null +++ b/test/fixtures/stdin-source-filter-youngerThan-olderThan.json @@ -0,0 +1,8 @@ +{ + "source": { + "filter": { + "olderThan": 3000, + "youngerThan": 80000 + } + } +} diff --git a/test/fixtures/stdin-source-filter-youngerThan.json b/test/fixtures/stdin-source-filter-youngerThan.json new file mode 100644 index 0000000..f3f1a57 --- /dev/null +++ b/test/fixtures/stdin-source-filter-youngerThan.json @@ -0,0 +1,7 @@ +{ + "source": { + "filter": { + "youngerThan": 3600 + } + } +}