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

feature(dataplanes): add filtered XDS config to drawers #3186

Merged
merged 6 commits into from
Dec 3, 2024

Conversation

johncowen
Copy link
Contributor

@johncowen johncowen commented Nov 14, 2024

Adds XDS configuration drawers to inbounds and outbounds so show only the listeners/clusters relevant to that inbound/outbound.

Closes #3182
Closes #3181

You can run this against a local cluster by setting a cookie like the following:

Screenshot 2024-11-25 at 11 28 49

note: I removed an annoying ESLint rule here https://eslint.org/docs/latest/rules/multiline-ternary#when-not-to-use-it . We don't have any conventions in regards to ternaries, do whatever works for you. Generally you've decided to use a ternary because the format you've personally chosen reads nicer - furthermore its pointless having a eslint rule to force wrapping of something that is designed for single lines. Not only that but the eslint rule we had makes these super hard to read.


Note: This will not pass lint tests and is purposefully an early WIP PRed for preview site purposes.


Notes taken during work:

Adding some pseudo code to help explain the filtering/selecting we are doing:

Inbounds

I use '127.0.0.1:0000' below in place of the actual dataplane.networking.address

  • dynamic_listeners[].name === '127.0.0.1:0000'
  • {dynamic_active_clusters, static_clusters}.cluster.load_assignment.endpoints[].lb_endpoints[].endpoint.address.socket_address.{address:port_value} === '127.0.0.1:0000' (I'm not totally sure we should be using this one)

Note for an inbound we do not know the type of the service (i.e. is it a _msvc_ a _mzsvc_ etc) so we can't filter by cluster name.


Improvements: we should look for inbound:ignore.ip.address:0000 use prefix/suffix because we need to be careful with ipv6.

  • dynamic_listeners[].name === 'inbound:ignore.ip.address:0000'
  • dynamic_active_clusters[].cluster.name === 'ignore.host:0000'

Outbounds

I use outbound below in place of the actual Envoy stats name (e.g. default_demo-app_kuma-demo_default_msvc_5000)

  • dynamic_active_clusters[].cluster.name === <outbound>
  • dynamic_endpoint_configs[].endpoint_config.cluster_name === <outbound>

Note we don't have any information about a specific outbound apart from the clusterName/envoy stats prefix. We can take information from the dataplane associated with the outbound, but not the outbound itself.

Improvements:

If we need to add more instance of filtering/selecting it would be helpful to express what needs to be done using the above examples

@johncowen johncowen changed the title feature(dataplanes): add filtered XDS config to inbound drawers [WIP] feature(dataplanes): add filtered XDS config to inbound drawers Nov 14, 2024
Copy link

netlify bot commented Nov 14, 2024

Deploy Preview for kuma-gui ready!

Name Link
🔨 Latest commit 3afdfd2
🔍 Latest deploy log https://app.netlify.com/sites/kuma-gui/deploys/674daf6b76aec10008ea717a
😎 Deploy Preview https://deploy-preview-3186--kuma-gui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@johncowen johncowen force-pushed the feature/inbound-config-drawer branch 3 times, most recently from 616b635 to 876dce4 Compare November 18, 2024 13:58
@johncowen johncowen force-pushed the feature/inbound-config-drawer branch 2 times, most recently from eef2826 to 6d92432 Compare November 20, 2024 16:14
@johncowen johncowen force-pushed the feature/inbound-config-drawer branch 2 times, most recently from 6c11ff6 to 268c360 Compare November 22, 2024 16:35
@johncowen johncowen force-pushed the feature/inbound-config-drawer branch from 268c360 to 60e74c5 Compare November 25, 2024 10:35
Signed-off-by: John Cowen <[email protected]>
@johncowen johncowen force-pushed the feature/inbound-config-drawer branch from 944f176 to c42fe8d Compare November 25, 2024 11:22
@johncowen johncowen changed the title [WIP] feature(dataplanes): add filtered XDS config to inbound drawers feature(dataplanes): add filtered XDS config to inbound drawers Nov 25, 2024
@johncowen johncowen marked this pull request as ready for review November 25, 2024 11:25
@johncowen johncowen requested a review from a team as a code owner November 25, 2024 11:25
@johncowen johncowen requested review from schogges and removed request for a team November 25, 2024 11:25
@lahabana
Copy link
Contributor

lahabana commented Nov 27, 2024

Looks great! There's only 1 bug with clusters

https://konghq.zoom.us/clips/share/A2F3MRZnZDRPSjZfT1E5bVhNRTRERWl1MnlnAQ

For the inbound issue I observe: kumahq/kuma#12123

@johncowen johncowen changed the title feature(dataplanes): add filtered XDS config to inbound drawers feature(dataplanes): add filtered XDS config to drawers Nov 28, 2024
@johncowen
Copy link
Contributor Author

PR to fix up the issue with clusters is here:

#3239

@schogges
Copy link
Contributor

schogges commented Nov 29, 2024

note: I removed an annoying ESLint rule here https://eslint.org/docs/latest/rules/multiline-ternary#when-not-to-use-it . We don't have any conventions in regards to ternaries, do whatever works for you. Generally you've decided to use a ternary because the format you've personally chosen reads nicer - furthermore its pointless having a eslint rule to force wrapping of something that is designed for single lines. Not only that but the eslint rule we had makes these super hard to read.

I agree with this 👍 since you speak about readability, I'd like to bring up no-nested-ternary 🙂 I think this might be a good addition to our lint rules as it enforces short and one-lined ternary expressions, which are great. But when it comes to more complex flows, I'd rather use if-else or a mix of ternary and if-else. Nesting ternaries hurts readability IMO. (But have not seen any nested ones yet tbh 😄 )

@johncowen
Copy link
Contributor Author

johncowen commented Nov 29, 2024

I agree with this 👍 since you speak about readability, I'd like to bring up no-nested-ternary 🙂

More than happy to take look at it.

The only thing is ternaries are about more than readability, they allow you to have type safety at runtime in javascript, which while I don't think is as important as the type safety, I believe is also a micro-performance improvement in javascript engines (but lets not get into micro-optimizations, thats side benefit)

Its not so much using the ternaries, its more the avoidance of using let.

let a = '1'
if(true) {
  a = '2'
}
// a is a string

vs

const a = true ? '2' : '1'
// a is '1' | '2'

In the second form:

  • The JS engine knows a can only ever be '1' or '2' , not any-string (in TS) or anything (in JS), and therefore optimize.
  • The JS engine knows that a will never be set again, and therefore optimize.

So I use these inline forms a lot (and did previous to Typescript) via ternaries and inline functions for try/catch and switch among other constructs for these reasons, not necessarily for readability. If there's a nested ternary somewhere there's a chance its for the above reasons.

I have an example of a change a made recently that outlines this, lemme try and find it.

edit:

Not a ternary but its the same idea, if you take a look at this code from a recent PR (😆 oh its actually this PR):

let type: 'gateway_builtin' | 'gateway_delegated' | 'proxy' = 'proxy'
if (name.includes('-gateway_builtin') || env('KUMA_DATAPLANE_TYPE', 'standard') === 'builtin') {
type = 'gateway_builtin'
} else if (name.includes('-gateway_delegated') || env('KUMA_DATAPLANE_TYPE', 'standard') === 'delegated') {
type = 'gateway_delegated'
}

In #3186 I'm changing it to this:

const type = (() => {
switch (true) {
case defaultType === 'builtin':
case name.includes('-gateway_builtin'):
return 'BUILTIN'
case defaultType === 'delegated':
case name.includes('-gateway_delegated'):
return 'DELEGATED'
default:
return 'STANDARD'
}
})()

Using the inline function gives me automatic type safety both in TS at build time and JS at runtime, and honestly in this case, in avoiding the multiple if conditionals the inline-function/switch is far easier to read to my eyes at least.

@schogges
Copy link
Contributor

I agree with this 👍 since you speak about readability, I'd like to bring up no-nested-ternary 🙂

More than happy to take look at it.

The only thing is ternaries are about more than readability, they allow you to have type safety at runtime in javascript, which while I don't think is as important as the type safety, I believe is also a micro-performance improvement in javascript engines (but lets not get into micro-optimizations, thats side benefit)

Its not so much using the ternaries, its more the avoidance of using let.

let a = '1'
if(true) {
  a = '2'
}
// a is a string

vs

const a = true ? '2' : '1'
// a is '1' | '2'

In the second form:

  • The JS engine knows a can only ever be '1' or '2' , not any-string (in TS) or anything (in JS), and therefore optimize.
  • The JS engine knows that a will never be set again, and therefore optimize.

So I use these inline forms a lot (and did previous to Typescript) via ternaries and inline functions for try/catch and switch among other constructs for these reasons, not necessarily for readability. If there's a nested ternary somewhere there's a chance its for the above reasons.

I have an example of a change a made recently that outlines this, lemme try and find it.

edit:

Not a ternary but its the same idea, if you take a look at this code from a recent PR (😆 oh its actually this PR):

let type: 'gateway_builtin' | 'gateway_delegated' | 'proxy' = 'proxy'
if (name.includes('-gateway_builtin') || env('KUMA_DATAPLANE_TYPE', 'standard') === 'builtin') {
type = 'gateway_builtin'
} else if (name.includes('-gateway_delegated') || env('KUMA_DATAPLANE_TYPE', 'standard') === 'delegated') {
type = 'gateway_delegated'
}

In #3186 I'm changing it to this:

const type = (() => {
switch (true) {
case defaultType === 'builtin':
case name.includes('-gateway_builtin'):
return 'BUILTIN'
case defaultType === 'delegated':
case name.includes('-gateway_delegated'):
return 'DELEGATED'
default:
return 'STANDARD'
}
})()

Using the inline function gives me automatic type safety both in TS at build time and JS at runtime, and honestly in this case, in avoiding the multiple if conditionals the inline-function/switch is far easier to read to my eyes at least.

Yeah, I like the switch-case 👍 😄 another great way of avoiding nested (or chained) ternaries, having the optimization benefits and it's a lot easier to read and understand.

Signed-off-by: John Cowen <[email protected]>
@johncowen
Copy link
Contributor Author

Oh look I found a nested-ternary:

dataplaneType: networking.type === 'gateway' ? dpTypes.builtin : typeof networking.gateway !== 'undefined' ? dpTypes.delegated : dpTypes.standard,

🤔 when I think about what the above file used to be like, I kinda prefer the direction it's going.

I think that, the fact that we have them already, and the type/js benefits I wouldn't be super keen on adding that rule, plus the more i think about it its very similar to saying "don't use multiple conditionals inside an if statement" (i.e. &&'s and ||'s)

If you feel super strong about it happy to reconsider, but at the moment it doesn't feel like a super important error causing problem that we might want to add a lint rule for.

Copy link
Contributor

@schogges schogges left a comment

Choose a reason for hiding this comment

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

LGTM! 👍

@schogges
Copy link
Contributor

Oh look I found a nested-ternary:

dataplaneType: networking.type === 'gateway' ? dpTypes.builtin : typeof networking.gateway !== 'undefined' ? dpTypes.delegated : dpTypes.standard,

🤔 when I think about what the above file used to be like, I kinda prefer the direction it's going.

I think that, the fact that we have them already, and the type/js benefits I wouldn't be super keen on adding that rule, plus the more i think about it its very similar to saying "don't use multiple conditionals inside an if statement" (i.e. &&'s and ||'s)

If you feel super strong about it happy to reconsider, but at the moment it doesn't feel like a super important error causing problem that we might want to add a lint rule for.

I think ternaries are getting unreadable a lot quicker when nesting than a complex boolean expression. But yeah, at some point it probably makes sense to outsource and group them into variables.
Anyways, will think about it and will probably bring it up again 🙂

Signed-off-by: John Cowen <[email protected]>
@johncowen
Copy link
Contributor Author

One last thing I wanted to do here thats vaguely related to above convo, I added fake.kuma.certificate for various reasons here. Then typically I had to stabilise a test because of that. I did it in separate commits in case.

I'll leave this hanging for a little while today, but if I hear no more I'll go ahead and merge seeing as I already have approval on everything else. But lmk if there's anything else

@johncowen johncowen merged commit d5cd4e2 into kumahq:master Dec 3, 2024
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add xds config tab to inbound tray ☔ Add XDS config tab to outbound and inbound view
3 participants