Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document typical "for all" patterns #1307

Closed
ghost opened this issue Apr 2, 2019 · 2 comments · Fixed by #1527
Closed

Document typical "for all" patterns #1307

ghost opened this issue Apr 2, 2019 · 2 comments · Fixed by #1527
Assignees
Labels

Comments

@ghost
Copy link

ghost commented Apr 2, 2019

I cannot find in the docs how to validate every element of the array

So, now I'm using this trick as a temporary solution


everyShouldSatisfyRequirement {
  input.elements
  exceptions := [element | input.elements[i] = element; element != "foo"]
  count(exceptions) = 0
}
@ashutosh-narkar
Copy link
Member

@tsandall
Copy link
Member

tsandall commented Apr 3, 2019

@almostprogrammer your solution is correct though you can omit the first expression (input.elements) because if input.elements were undefined or empty then exceptions will be []. Note, if you want to ensure that every element satisfies some requirements AND the elements array is non-empty, you could adjust the first expression to be input.request != [].

The only other thing I'd change is to rename i to _ and use := instead of =. For example:

all_elements_satisfy_requirements {
   exceptions := [e | e := input.elements[_]; e != "foo"]
   count(exceptions) == 0
}

The alternative that @ashutosh-narkar pointed out is to use negation (not) instead of comprehensions.

all_elements_satisfy_requirements {
   not some_elements_violate_requirements
}

some_elements_violate_requirements {
   e := input.elements[_]
   e != "foo"
}

Comprehensions and negation are the two typical ways of implementing "for all" inside Rego. There is a third way which involves using the all built-in function which I'm personally not a fan of (because it requires combination of comprehensions, helper functions, and built-in calls).

all_elements_satisfy_requirements {
  satisfied := [yes | e := input.elements[_]; yes := satisfies_requirements(e)]
  all(satisfied)
}

satisfies_requirements(e) {
  e != "foo" 
} else = false {   # NOTE: bare `else` and `default` on rules with args not suppored today, hence `{ true }` is needed
   true
}

Note, this is a very common question and I don't think we have good coverage of it in the FAQ or cheat sheet. I'm going to edit the title an label the issue so that we can come back and fix the docs.

@tsandall tsandall changed the title Question: passing checks only if every element of array satisfies a requirement Document typical "for all" patterns Apr 3, 2019
@tsandall tsandall added the docs label Apr 3, 2019
@tsandall tsandall self-assigned this Apr 12, 2019
tsandall added a commit to tsandall/opa that referenced this issue Jun 27, 2019
This is a common question that comes up. Until we have a keyword that
lets users express "FOR ALL" we should have docs we can point to.

Fixes open-policy-agent#1307

Signed-off-by: Torin Sandall <torinsandall@gmail.com>
tsandall added a commit that referenced this issue Jun 28, 2019
This is a common question that comes up. Until we have a keyword that
lets users express "FOR ALL" we should have docs we can point to.

Fixes #1307

Signed-off-by: Torin Sandall <torinsandall@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants