Skip to content

Commit

Permalink
Merge pull request #47 from bats-core/#46
Browse files Browse the repository at this point in the history
#46 Fix regexp support for resource names
  • Loading branch information
vincent-zurczak authored Jul 17, 2024
2 parents 5dca7f5 + fde4db8 commit cc98de0
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 9 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -297,15 +305,11 @@ verify "there are more than <number> <resource-type> named '<regular-expression>
verify "there are less than <number> <resource-type> named '<regular-expression>'"
```

*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):

Expand Down
32 changes: 28 additions & 4 deletions lib/detik.bash
Original file line number Diff line number Diff line change
Expand Up @@ -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-----"
Expand All @@ -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
Expand Down Expand Up @@ -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-----"
Expand Down Expand Up @@ -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
}
20 changes: 20 additions & 0 deletions tests/test.detik.try.to.verify.is.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]
Expand All @@ -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 " \
Expand Down
9 changes: 9 additions & 0 deletions tests/test.detik.verify.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions tests/test.linter.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]
}


Expand Down

0 comments on commit cc98de0

Please sign in to comment.