diff --git a/README.md b/README.md index 91f1a20..fb0b2a6 100644 --- a/README.md +++ b/README.md @@ -279,6 +279,14 @@ The syntax is quite simple and may be easily adapted for other solutions, such a ## Syntax Reference +For all the available sentences, both a resource name and a resource type are expected. +The resource name can be a simple string (e.g. `nginx`) or a regular expression +(e.g. `^nginx-[a-z0-9]{9,10}-[a-z0-9]{5}\$`), while the resource type is one of +the K8s ones (e.g. `pods`, `po`, `services`, `svc`...) or a CRD. See +[https://kubernetes.io/docs/reference/kubectl/overview/#resource-types](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) for a complete reference of the official resources. The available custom resources (e.g. +`settings.management.cattle.io`) will depend on your cluster setup. + + ### Counting Resources Verify there are N resources of this type with this name pattern. @@ -297,15 +305,11 @@ verify "there are more than named ' verify "there are less than named ''" ``` -*resource-type* is one of the K8s ones (e.g. `pods`, `po`, `services`, `svc`...). -See [https://kubernetes.io/docs/reference/kubectl/overview/#resource-types](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) for a complete reference. - - > :warning: This simple assertion may fail sometimes. > > As an example, if you count the number of PODs, run your test and then kill the POD, they will still be listed, with the `TERMINATING` state. > -> So, most of the time, you will want to verify the number of instances with a given property value. Example: count the number of PODs with a given name pattern and having the `started` status. +> So, most of the time, you will want to verify the number of instances with a given property value. Example: count the number of PODs with a given name pattern and having the `running` status. Hence this additional syntax (using [next section](#verifying-property-values) documentation to verify additionnal properties): diff --git a/lib/detik.bash b/lib/detik.bash index d84c113..5d73283 100644 --- a/lib/detik.bash +++ b/lib/detik.bash @@ -153,7 +153,11 @@ verify() { echo "Valid expression. Verification in progress..." query=$(build_k8s_request "") client_with_options=$(build_k8s_client_with_options) - result=$(eval $client_with_options get $resource $query | grep $name | tail -n +1 | wc -l | tr -d '[:space:]') + result=$(eval $client_with_options get $resource $query \ + | tail -n +2 \ + | filter_by_resource_name "$name" \ + | wc -l \ + | tr -d '[:space:]') # Debug? detik_debug "-----DETIK:begin-----" @@ -173,7 +177,7 @@ verify() { echo "Found $result $resource named $name (less than $card as expected)." else echo "Found $result $resource named $name (instead of less than $card expected)." - return 3 + return 3 fi elif [[ "$exp" =~ "more than" ]]; then if [[ "$result" -gt "$card" ]]; then @@ -243,10 +247,12 @@ verify_value() { expected_count="$6" exp="$7" - # List the items and remove the first line (the one that contains the column names) + # 1. Query / list the items + # 2. Remove the first line (the one that contains the column names) + # 3. Filter by resource name query=$(build_k8s_request "$property") client_with_options=$(build_k8s_client_with_options) - result=$(eval $client_with_options get $resource $query | grep $name | tail -n +1) + result=$(eval $client_with_options get $resource $query | tail -n +2 | filter_by_resource_name "$name") # Debug? detik_debug "-----DETIK:begin-----" @@ -380,3 +386,21 @@ build_k8s_client_with_options() { echo "$client_with_options" } + + +# Filters results by resource name (or name pattern). +# The results are directly read, they are not passed as variables. +# +# @param $1 the resource name or name pattern +# @return 0 +filter_by_resource_name() { + + # For all the output lines... + while IFS= read -r line; do + # ... extract the resource name (first column) + # and only keep the lines where the resource name matches + if echo "$line" | cut -d ' ' -f1 | grep -qE $1; then + echo "$line" + fi + done +} diff --git a/tests/test.detik.try.to.verify.is.bats b/tests/test.detik.try.to.verify.is.bats index 42f38d9..f5e3350 100755 --- a/tests/test.detik.try.to.verify.is.bats +++ b/tests/test.detik.try.to.verify.is.bats @@ -145,6 +145,16 @@ mytest_deployment(){ } +@test "trying to find of a POD with an extended pattern name" { + run try "at most 1 times every 5s to get pod named '^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{5}\$' and verify that 'status' is 'running'" + [ "$status" -eq 0 ] + [ ${#lines[@]} -eq 3 ] + [ "${lines[0]}" = "Valid expression. Verification in progress..." ] + [ "${lines[1]}" = "nginx-deployment-75675f5897-6dg9r has the right value (running)." ] + [ "${lines[2]}" = "nginx-deployment-75675f5897-gstkw has the right value (running)." ] +} + + @test "trying to verify the status of a POD with an invalid pattern name" { run try "at most 1 times every 1s to get pods named 'ngin.+x' and verify that 'status' is 'running'" [ "$status" -eq 3 ] @@ -154,6 +164,16 @@ mytest_deployment(){ } +@test "trying to find of a POD with an invalid extended pattern name" { + run try "at most 1 times every 1s to find 2 pods named '^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{4}\$' with 'status' being 'running'" + [ "$status" -eq 3 ] + [ ${#lines[@]} -eq 3 ] + [ "${lines[0]}" = "Valid expression. Verification in progress..." ] + [ "${lines[1]}" = "No resource of type 'pods' was found with the name '^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{4}\$'." ] + [ "${lines[2]}" = "Expected 2 pods named ^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{4}\$ to have this value (running). Found 0." ] +} + + @test "trying to verify the status of a POD with the lower-case syntax (multi-lines)" { run try " at most 5 times every 5s to get pods " \ " named 'nginx' and " \ diff --git a/tests/test.detik.verify.bats b/tests/test.detik.verify.bats index 641e530..c467fa8 100755 --- a/tests/test.detik.verify.bats +++ b/tests/test.detik.verify.bats @@ -76,6 +76,15 @@ mytest_with_namespace() { } +@test "verifying the number of PODs with an extended pattern syntax (exact number, 0 as singular)" { + run verify "There are 2 PODS named '^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{5}\$'" + [ "$status" -eq 0 ] + [ ${#lines[@]} -eq 2 ] + [ "${lines[0]}" = "Valid expression. Verification in progress..." ] + [ "${lines[1]}" = "Found 2 pods named ^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{5}\$ (as expected)." ] +} + + @test "verifying the number of resources with their type including dots" { # The value is not important. We want to make sure resource # types with dots is supported. diff --git a/tests/test.linter.bats b/tests/test.linter.bats index c819339..90b3e3d 100755 --- a/tests/test.linter.bats +++ b/tests/test.linter.bats @@ -72,6 +72,9 @@ setup() { run verify_against_pattern "at most 5 times eVery 5s to GET pods named nginx' and verify that 'status' matches '^RUNNING$'" "$try_regex_verify_matches" [ "$status" -eq 1 ] + + run verify_against_pattern "at most 5 times eVery 5s to GET pods named '^nginx-deployment-[a-z0-9]{9,10}-[a-z0-9]{4}\$' and verify that 'status' matches '^RUNNING$'" "$try_regex_verify_matches" + [ "$status" -eq 0 ] }