Evaluating Istio rule match using GreaterThan / LessThan - istio

Looking at the capabilities of Istio Rule.match, .. https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1/#Rule , how would one match on GreaterThan / LessThan , as opposed to just existance / equality checks
Eg. How would I be able to achieve something like this (header value > 24)
spec:
match: match((request.headers["some-header"] | 24) >"24")

The rule mentioned in the question will not work because of mismatched attribute types.
However, it is possible to do with Common Expression Language (CEL).
You can enable CEL in istio by using the policy.istio.io/lang annotation (set it to CEL).
Then by using Type Values from the List of Standard Definitions we can use create functions to parse values into different types.
For example: int() that gets a string and produces an int that we can
then compare with _>_ (int, int) -> bool.

Related

Case insensitive option with Regex.compile/2

I'm attempting to build a caseless regex binary using Regex.compile/2 but can't seem to find an example on how the option should be set.
Regex.compile("^(foo):?", :caseless)
** (FunctionClauseError) no function clause matching in Regex.compile/3
The following arguments were given to Regex.compile/3:
# 1
"^(foo):?"
# 2
:caseless
# 3
"8.41 2017-07-05"
(elixir) lib/regex.ex:140: Regex.compile/3
In short
According to the link you provided, options need to be provisioned as a list as you can provide multiple options. The following should work:
Regex.compile("^(foo):?", [:caseless])
In more detail
The type specification is as follows:
compile(source, options \\ "")
compile(binary(), binary() | [term()]) :: {:ok, t()} | {:error, any()}
The second line is the type specification in dialyzer and basically states that the function compile accepts two arguments:
The first one is a binary, corresponding to your "^(foo):?"
The second one is either a binary, or either a list containing several terms.
The return value will be either {:ok, t()} in the case of success, where t() is a %Regex{} struct or either will be {:error, any()} in the case of an error.
Coming back to the discussion of the second parameter, in the case of a list, you will need to leverage the various options as mentioned here.
In the case of binary, you can provide the second argument as a one letter abbreviation. So whereas the following will fail:
Regex.compile("^(foo):?", "caseless")
The following on the other hand succeeds:
Regex.compile("^(foo):?", "i")
The mapping you can get from the table of the various module modifiers I linked to above.
The main difference between the approaches stems from the fact that Erlang Regex as powered by :re builds on top of the PCRE standard. According to that standard, the various module modifiers are handled by the single lower case letters, such as i, u etc.. So you could combine accordingly both options with binary as follows:
Regex.compile("^(foo):?", "iu")
which technically speaking should give you the equivalent of:
Regex.compile("^(foo):?", [:caseless, :unicode])
This allows you to communicate about Regex in Erlang and in Elixir through either the language specifications, or either the PCRE specifications.
Highly Advanced Details
As the OP rightly pointed out in the comments, there is some confusion as to why the Regex produced in two different ways(e.g. through options as list vs options as binary) looks differently.
To explain this discrepancy in more detail, consider the following scenarios:
r0 = Regex.compile!("(foo):?") ---> ~r/(foo):?/
r1 = Regex.compile!("(foo):?", "i") ---> ~r/(foo):?/i
--->~r/(foo):?/# ?????? WHERE IS THEi` ?????
When confronted with this, one might gain the impression that the Elixir Regex is broken. r0 and r2 are identical and different from r1.
However, functionality wise, r2 behaves like r1, not like r0, consider the following examples as shamelessly inspired by the comment of the OP:
Regex.replace(r0, "Foo: bar", "") ---> "Foo: bar"
Regex.replace(r1, "Foo: bar", "") ---> " bar"
Regex.replace(r2, "Foo: bar", "") ---> " bar"
So how is this possible?
If you recall from above, e.g. pertaining to the explanation of the type t(), a Regex in Elixir is nothing but a struct under the hood.
A Regex may be presented beautifully in the following way: ~r/(foo):?/, but in reality it is nothing but something like this:
%Regex{ opts: opts, re_pattern: re_pattern, re_version: re_version, source: source }
Now, from all those struct fields, the only thing that counts at the end of the day is what is under: re_pattern. That will contain the fully compiled Regex with all the options. So we find that accordingly:
r1.re_pattern == r2.re_pattern
But
r0.re_pattern != r2.re_pattern
As far as the opts field is concerned, that is a container solely reserved for the options in binary format. So you will find that:
- r0.opts == r2.opts == ""
Whereas:
- r1.opts == "i"
These same opts fields are utilized to beautifully display the options at the end of Regex accordingly, so you will see:
~r/(foo):?/ for both r0 as well as r2
But you will see:
~r/(foo):?/i for both r1
on account of the opts fields differing from each other.
It is for this reason that you could manually update the Regex if you would like it to look more consistent by doing this for instance:
%{r2 | opts: "i"} ---> ~r/(foo):?/i
Except for the field, re_pattern, none of the other fields have any functional influence to the actual Regex. Those other fields are merely there for the purpose of documentation only.
Next, on the basis of the source code, you can see that binary options get translated to the list version of options because that is how Erlang regex engine, :re expects them to be.
Even though not difficult in itself, the Elixir core team have opted not to provide translation for the reverse, e.g. from the actual list of module modifier atoms to the equivalent PCRE binary option, thus you end up with the opts field remaining empty and bereft of the corresponding options in PCRE binary format and thus, you end up with the defective rendering of the Regex as evidenced by the discrepancy above.
Above I have only delved into the mechanics that explain the discrepancy, however, whether such a discrepancy is warranted or not is another question in itself. I would be immensely grateful if someone with more insight than me could be so kind as to clarify if there is any way to defend such a discrepancy.
Conclusion
r0 = Regex.compile!("(foo):?") ---> ~r/(foo):?/
r1 = Regex.compile!("(foo):?", "i") ---> ~r/(foo):?/i
r2 = Regex.compile!("(foo):?", [:caseless]) ---> ~r/(foo):?/
r1 and r2 may look different, but they behave exactly the same.

Why are there 2 parentheses in EC.element_to_be_clickable((By.CSS_SELECTOR, "css_selector")))?

I was simply wondering when using Selenium for python why there are 2 parentheses in between the element_to_be_clickable and the By methods, such as:
WebDriverWait(browser, 50).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "css_selector")))
This is also visble in the docs - http://selenium-python.readthedocs.io/waits.html
Any answers?
Cheers
According to the API documentation the method element_to_be_clickable expects one argument: a locator. A locator is a tuple of (by, path).
So the inner pair of parentheses are for the tuple literal, while the outer parentheses are for bounding the function parameters (only one in this case).

Jax-RS overloading methods/paths order of execution

I am writing an API for my app, and I am confused about how Jax-RS deals with certain scenarios
For example, I define two paths:
#Path("user/{name : [a-zA-Z]+}")
and
#Path("user/me")
The first path that I specified clearly encompasses the second path since the regular expression includes all letters a-z. However, the program doesn't seem to have an issue with this. Is it because it defaults to the most specific path (i.e. /me and then looks for the regular expression)?
Furthermore, what happens if I define two regular expressions as the path with some overlap. Is there a default method which will be called?
Say I want to create three paths for three different methods:
#Path{"user/{name : [a-zA-Z]+}")
#Path("user/{id : \\d+}")
#Path("user/me")
Is this best practice/appropriate? How will it know which method to call?
Thank you in advance for any clarification.
This is in the spec in "Matching Requests to Resource Methods"
Sort E using (1) the number of literal characters in each member as the primary key (descending order), (2) the number of capturing groups as a secondary key (descending order), (3) the number of capturing groups with non-default regular expressions (i.e. not ‘([^ /]+?)’) as the tertiary key (descending order), ...
What happens is the candidate methods are sorted by specified ordered "key". I highlight them in bold.
The first sort key is the number of literal characters. So for these three
#Path{"user/{name : [a-zA-Z]+}")
#Path("user/{id : \\d+}")
#Path("user/me")
if the requested URI is ../user/me, the last one will always be chosen, as it has the most literal characters (7, / counts). The others only have 5.
Aside from ../users/me anything else ../users/.. will depend on the regex. In your case one matches only numbers and one matches only letters. There is no way for these two regexes to overlap. So it will match accordingly.
Now just for fun, let's say we have
#Path{"user/{name : .*}")
#Path("user/{id : \\d+}")
#Path("user/me")
If you look at the top two, we now have overlapping regexes. The first will match all numbers, as will the second one. So which one will be used? We can't make any assumptions. This is a level of ambiguity not specified and I've seen different behavior from different implementations. AFAIK, there is no concept of a "best matching" regex. Either it matches or it doesn't.
But what if we wanted the {id : \\d+} to always be checked first. If it matches numbers then that should be selected. We can hack it based on the specification. The spec talks about "capturing groups" which are basically the {..}s. The second sorting key is the number of capturing groups. The way we could hack it is to add another "optional" group
#Path{"user/{name : .*}")
#Path("user/{id : \\d+}{dummy: (/)?}")
Now the latter has more capturing groups so it will always be ahead in the sort. All it does is allow an optional /, which doesn't really affect the API, but insures that if the request URI is all numbers, this path will always be chose.
You can see a discussion with some test cases in this answer

Writing grammar rules in SML Using Regular Expressions

I want to write a converter for iCalendar to CSV in SML. Hence, I need to write grammar rules for it. I understand that certain rules can be written by defining them as datatype. To begin with, I am facing problems to write rules for Regular Expressions (terminals).
As an example, I want to write the given Regex in SML :
label → [a-zA-Z0-9-]+
Can anybody tell me how to write this rule in SML?
EDIT
So far, I have declared a datatype variables that denotes the various variables of the grammar.
datatype variables = Label of String
I have declared a function isLabel. It takes as input s (of type string) and returns Label(s) if it satisfies the given regex (by checking if ASCII values lie in the given range) else raises exception. I gotta feeling that I have found the way to solve.
Other symbols/variables of the grammar can be defined similarly in the datatype variables.
See Unix Programming with Standard ML page 163+ for an example of SML/NJ's regular expression library in action.
Steps:
Add SML/NJ Library. In the smlnj REPL use:
CM.make "$/regexp-lib.cm"
Make a regular expression Engine:
structure RE = RegExpFn (structure P = AwkSyntax
structure E = BackTrackEngine)
Define label:
val label = RE.compileString "[a-zA-Z0-9-]+"
Define a target:
val target = "ab9A-f"
Match label against target:
val match = StringCvt.scanString (RE.find label) target
Extract values from match according to program logic.

SPARQL regexp with variables

I am trying to perform a relative simple regex query, however it uses a variable inside the regexp. Is sparql not capable of using these kind of concatenation or am I using a wrong method? What I am trying to query is the following:
SELECT *
WHERE {
?part local:part_start ?start .
?chunk local:long_region ?long_region
BIND(REPLACE(?long_region, ".{"+?start+"}(.{10}).*", "$1") AS ?regionX)
}
I will end up with a small part from a long region of characters according to a start location and 10 characters further.
No + cannot be used for string concatenation in most SPARQL implementations, in principal an implementation can support this as an extended operator mapping but I'm not aware of any that do.
Instead you can use the standard CONCAT() function to achieve your aim provided you are using a SPARQL 1.1 compliant engine:
SELECT *
WHERE {
?part local:part_start ?start .
?chunk local:long_region ?long_region
BIND(REPLACE(?long_region, CONCAT(".{", ?start, "}(.{10}).*"), "$1") AS ?regionX)
}