Rego write a test for every entry with a condition has to have another condition

68 views Asked by At

Example data:

{
    "serviceA_primary": {
        "foo": 1
        "bar": 2
    },
    "serviceA_secondary": {
        "foo": 1,
        "bar": 3
    },
    "serviceB_primary": {
        "bar": 2
    },
    "serviceB_secondary": {
        "bar": 3
    }
    ...
}

I want to write a test that for every key with serviceA in the name, it's bar value matches with the bar value of the corresponding serviceB.

For example, serviceA_primary.bar == serviceB_primary.bar and serviceA_secondary.bar == serviceB_secondary.bar

Honestly don't really know how to approach. I was planning on filtering out serviceB and then for every serivceA do something. But I don't think it's the right approach.

deny_due_to_mismatch[res] if {
    some key, val in input
    res := {k: v |
        regex.match(`serviceA`, key)
        k := mpkhs_coord_name
        v := mpkhs_coord_info
    }
}
1

There are 1 answers

1
tsandall On BEST ANSWER

TLDR; This logic is simple to express using the every keyword (which you can enable with import rego.v1). For example:

every_serviceA_is_valid if {
    every name, value in service_a {
        value.bar == service_b[name].bar
    }
}

To make this happen, I defined two helper rules service_a and service_b that generate maps containing the respective services, keyed by the suffixes (e.g., "primary", "secondary"`, etc.)

service_a[x] := value if {
    some name, value in input
    startswith(name, "serviceA_")
    x := substring(name, count("serviceA_"), -1)
}

service_b[x] := value if {
    some name, value in input
    startswith(name, "serviceB_")
    x := substring(name, count("serviceB_"), -1)
}

There is duplicated logic here, however, if there will only ever be serviceA and serviceB then I think this is fine. On the other hand, if you want to generalize the logic you could write a function that returns a map of services for a given name/prefix. For example:

services(name) := {key: value |
    some k, value in input
    prefix := sprintf("%v_", [name])
    startswith(k, prefix)
    key := substring(k, count(prefix), -1)
}

Then you could use the function like so:

every_serviceA_is_valid_v2 if {
    every name, value in services("serviceA") {
        value.bar == services("serviceB")[name].bar
    }
}

Here's a full example in the playground: https://play.openpolicyagent.org/p/53Hh2wU2Uh