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

🐛 Do not return the type of the predicate for if blocks #3412

Merged
merged 1 commit into from
Feb 26, 2024

Conversation

jaym
Copy link
Contributor

@jaym jaym commented Feb 22, 2024

When there were errors, ifCallV2 would return the type of the predicate for the result of the if block.

That becomes problematic for a query like the following:

if (file('/etc/amazon/').exists) {
  return "AWS"
} else if ( users.any( name == 'ec2-user' || name == 'ec2-instance-connect' ) ) {
  return "AWS"
} else if ( machine.baseboard.manufacturer == 'Amazon EC2') {
  return "AWS"
} else if ( asset.platform == "cos" ) {
  return "GCP"
} else if ( file('/etc/google_instance_id').exists ) {
  return "GCP"
} else if ( file('/var/lib/waagent/').exists ) {
  return "Azure"
} else if ( file('/var/lib/dhcp/dhclient.enp1s0.leases').exists && file('/var/lib/dhcp/dhclient.enp1s0.leases').content.lines.contains( /unknown-245/ ) ) {
  return "Azure"
} else {
  return "Unknown"
}

If you cannot run machine.baseboard.manufacturer, for example if you're not root, an error is returned. The type of the result is boolean, when it should be string. You then get a message like the following:

failed to send datapoints error="1 error occurred:\n\t* failed to store data for \"HTCzrF9d2vMJ1iUZsoMcMwaC8XQ7bvQE5nLxC0I5cSBlLXawpmn74WyIEaTgXuUmz/C5iRSeedT3eBg9h6xx8A==\", types don't match: expected string, got bool\n\n"

@jaym
Copy link
Contributor Author

jaym commented Feb 22, 2024

i haven't been able to get this to fail with the mock tests. It also doesn't seem to happen all the time. For example, an error in file.content doesn't produce such an error

@jaym
Copy link
Contributor Author

jaym commented Feb 22, 2024

I think I kind of understand it in a hand wavy way. In the case of file.content, which does print any error even though a file doesn't exist, we are able to create the file resource, and error out when we access the field content. This triggers some special code called triggerChainError which sets everything in the chain to the error value with no type. machine.baseboard.manufacturer produces an error much earlier. It produces an error on machine.baseboard, which is a resource. Since its not an error on a field, it doesn't go through the same triggerChainError.

As an aside, I don't really think we need triggerChainError. It really feels like the builtins should decide how to handle errors. For example, if errors were to be treated as false, triggerChainError would prevent that from happening because it would report an error for the entire chain before the builtin if could do its thing.

Copy link
Member

@arlimus arlimus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for analyzing this, I can see that return types inside of the conditionals that are failing can lead to the whole thing to fall apart. Let's get this merged first to move forward.

@arlimus
Copy link
Member

arlimus commented Feb 26, 2024

Let's come up with a decision around how we want to handle errors in conditionals. I'm somewhat in favor of treating them as false conditions and moving forward.

Another approach could be to iterate all conditional branches to see if a truthy branch is found. If none is encountered, it could still opt to expose errors (as seen in other frameworks). The downside with this approach is that it will set user expectations to see errors, but all of a sudden hide them if a truthy branch is found.

Ultimately it's a decision about the behavior of this code.

When there were errors, `ifCallV2` would return the type of the
predicate for the result of the if block.

That becomes problematic for a query like the following:
```
if (file('/etc/amazon/').exists) {
  return "AWS"
} else if ( users.any( name == 'ec2-user' || name == 'ec2-instance-connect' ) ) {
  return "AWS"
} else if ( machine.baseboard.manufacturer == 'Amazon EC2') {
  return "AWS"
} else if ( asset.platform == "cos" ) {
  return "GCP"
} else if ( file('/etc/google_instance_id').exists ) {
  return "GCP"
} else if ( file('/var/lib/waagent/').exists ) {
  return "Azure"
} else if ( file('/var/lib/dhcp/dhclient.enp1s0.leases').exists && file('/var/lib/dhcp/dhclient.enp1s0.leases').content.lines.contains( /unknown-245/ ) ) {
  return "Azure"
} else {
  return "Unknown"
}
```

If you cannot run `machine.baseboard.manufacturer`, for example if
you're not root, an error is returned. The type of the result is
boolean, when it should be string. You then get a message like the
following:

```
failed to send datapoints error="1 error occurred:\n\t* failed to store data for \"HTCzrF9d2vMJ1iUZsoMcMwaC8XQ7bvQE5nLxC0I5cSBlLXawpmn74WyIEaTgXuUmz/C5iRSeedT3eBg9h6xx8A==\", types don't match: expected string, got bool\n\n"
```
@jaym jaym force-pushed the jdm/server-6644-1 branch from f00244e to b2e43f2 Compare February 26, 2024 20:40
Copy link
Contributor

Test Results

2 829 tests  ±0   2 828 ✅ ±0   1m 15s ⏱️ -7s
  186 suites ±0       1 💤 ±0 
    5 files   ±0       0 ❌ ±0 

Results for commit b2e43f2. ± Comparison against base commit 7e8f0bd.

This pull request removes 6 and adds 6 tests. Note that renamed tests count towards both.
go.mondoo.com/cnquery/v10/llx ‑ TestRawData_JSON/0001-01-01_00:00:00_+0000_UTC
go.mondoo.com/cnquery/v10/llx ‑ TestRawData_JSON/292277026596-12-04_15:30:07_+0000_UTC
go.mondoo.com/cnquery/v10/llx ‑ TestRawData_JSON/292277026596-12-04_15:30:09_+0000_UTC
go.mondoo.com/cnquery/v10/llx ‑ TestSuccess/2024-02-26_09:00:01.870457051_+0000_UTC_m=+0.016473257
go.mondoo.com/cnquery/v10/llx ‑ TestTruthy/2024-02-26_09:00:01.870457051_+0000_UTC_m=+0.016473257
go.mondoo.com/cnquery/v10/llx ‑ TestTruthy/2024-02-26_09:00:01.870457051_+0000_UTC_m=+0.016473257#01
go.mondoo.com/cnquery/v10/llx ‑ TestRawData_JSON/0001-01-01_00:53:28_+0053_LMT
go.mondoo.com/cnquery/v10/llx ‑ TestRawData_JSON/292277026596-12-04_16:23:37_+0053_LMT
go.mondoo.com/cnquery/v10/llx ‑ TestRawData_JSON/292277026596-12-04_16:30:07_+0100_CET
go.mondoo.com/cnquery/v10/llx ‑ TestSuccess/2024-02-26_21:42:06.113258173_+0100_CET_m=+0.007185543
go.mondoo.com/cnquery/v10/llx ‑ TestTruthy/2024-02-26_21:42:06.113258173_+0100_CET_m=+0.007185543
go.mondoo.com/cnquery/v10/llx ‑ TestTruthy/2024-02-26_21:42:06.113258173_+0100_CET_m=+0.007185543#01

@jaym jaym merged commit a6243ff into main Feb 26, 2024
14 checks passed
@jaym jaym deleted the jdm/server-6644-1 branch February 26, 2024 22:06
@github-actions github-actions bot locked and limited conversation to collaborators Feb 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants