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
Make the configuration conversion stable #1990
Conversation
4f440c8
to
dfdddc1
Compare
internal/bgp/frr/frr_test.go
Outdated
if err != nil { | ||
t.Fatalf("Could not advertise prefix: %s", err) | ||
} | ||
err = session1.Set(adv1, adv2) | ||
|
||
rand.Shuffle(len(advs), func(i, j int) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add more attempts to shuffle and check like in config_conversion_test.go
so we'll be more confident?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will require a bit of reworking, as I don't want to pay the FRR extra effort every iteration. Let me try to fix it.
v1.ConfigMap{}) | ||
|
||
if err != nil { | ||
t.Fatalf("conversion failed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err print missing
v1.ConfigMap{}) | ||
|
||
if err != nil { | ||
t.Fatalf("conversion failed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err print missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
if !reflect.DeepEqual(config, oldConfig) { | ||
t.Fatalf("conversion is not stable, seed %d, %v\n %v\n", seed, spew.Sdump(config), spew.Sdump(oldConfig)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's add these small details so the output will be clearer
t.Fatalf("conversion is not stable, seed %d, %v\n %v\n", seed, spew.Sdump(config), spew.Sdump(oldConfig)) | |
t.Fatalf("conversion is not stable, seed %d, got: %v\n expected: %v\n", seed, spew.Sdump(config), spew.Sdump(oldConfig)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The got - expected here makes less sense because we don't know which version is the expected (right) one. I'll name them current - previous
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
if !reflect.DeepEqual(config, oldConfig) { | ||
t.Fatalf("conversion is not stable, seed %d, %v\n %v\n", seed, spew.Sdump(config), spew.Sdump(oldConfig)) | ||
} | ||
oldConfig = config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can omit this assignment as the value doesn't change, and keep comparing to the same oldConfig.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, makes sense. Fixed
cfg, err := toConfig(r.ValidateConfig, | ||
ipAddressPools.Items, | ||
[]metallbv1beta2.BGPPeer{}, | ||
[]metallbv1beta1.BFDProfile{}, | ||
[]metallbv1beta1.L2Advertisement{}, | ||
[]metallbv1beta1.BGPAdvertisement{}, | ||
addressPools.Items, | ||
communities.Items, | ||
map[string]corev1.Secret{}, | ||
[]corev1.Node{}, | ||
namespaces.Items, | ||
corev1.ConfigMap{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a little hard to read, plus we'll need to update the parameters list when a new CRD is added. why not reuse the ClusterResources
struct, consume it as the input, and re-assign its fields with the sorted copy?
I would go even a step further and split toConfig
into two methods, first only the logic of sorting the resources, so we'll have a sortedResources
, and then call the config.For
on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a little hard to read, plus we'll need to update the parameters list when a new CRD is added.
What I was totally afraid of was to forget the sorting in case a new CRD is added. I wanted to make it really hard to forget, and that's why I came up with the long list. But I guess I can fix that by doing the sorting in the toConfig as you said. Let me try to get a stab at it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, with this new version, assuming we add e2e tests covering new CRD, we'll be forced to add it
When translating the configuration coming from the k8s api to the internal one, the outcome depends on the order in which the cache returns us the various items. This may cause unnecessary reloads. In order to avoid this, we pre-order the list of items to feed the conversion with. The sorting is done in a conversion function in the controller (rather than the config package) in order to make it harder to forget to add the sorting action. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
dfdddc1
to
6359a2c
Compare
/lgtm |
6359a2c
to
a3b3280
Compare
The resulting frr configuration was influenced by the order of the advertisements, which ultimately come from a map (which doesn't guarantee the order). Here we sort to make the configuration stable, and to allow us to catch non-changing configurations updates. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
a3b3280
to
9faeb1f
Compare
When translating the configuration coming from the k8s api to the internal one, the outcome depends on the order in which the cache returns us the various items. This may cause unnecessary reloads.
In order to avoid this, we pre-order the list of items to feed the conversion with.
The sorting is done in a conversion function in the controller (rather than the config package) in order to make it harder to forget to add the sorting action.