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
add patches to virt-operator #3612
add patches to virt-operator #3612
Conversation
Skipping CI for Draft Pull Request. |
@davidvossel @rmohr does this approach look correct to implement for all components? |
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 left one comment about code structure. The other kind of high level comment I have is how do we detect when a new patch has been added which should result in rollling out a new install strategy.
So for example, if someone installs kubevirt, then mutates the kubevirt spec to include a patch, how does our controller know to roll out that change. Right now it's only keying off image name/registry. We
if err != nil { | ||
return nil, fmt.Errorf("error generating virt-apiserver deployment %v", err) | ||
} | ||
strategy.deployments = append(strategy.deployments, apiDeployment) | ||
|
||
controller, err := components.NewControllerDeployment(config.GetNamespace(), config.GetImageRegistry(), config.GetImagePrefix(), config.GetControllerVersion(), config.GetLauncherVersion(), config.GetImagePullPolicy(), config.GetVerbosity(), config.GetExtraEnv()) | ||
controller, err := components.NewControllerDeployment(config.GetNamespace(), config.GetImageRegistry(), config.GetImagePrefix(), config.GetControllerVersion(), config.GetLauncherVersion(), config.GetImagePullPolicy(), config.GetVerbosity(), config.GetExtraEnv(), config.GetPatchesForResource("Deployment", components.ControllerDeploymentName)) |
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 wonder if instead of passing in the patches to each create function (like deployments, api, daemonset, etc...) if we could just loop over all the objects at the of this GenerateCurrentInstallStrategy instead.
Something like
// services
for i, entry := range strategy.services {
strategy.services[i], err = applyPatches(entry, getPatchesForResource(.....))
if err != nil {
return nil, err
}
}
// deployments
for i, entry := range strategy.deployments {
strategy.deployments[i], err = applyPatches(entry, getPatchesForResource(.....))
if err != nil {
return nil, err
}
}
maybe there's even a generic function that can be used to do this so it would be as simple as
genericApplyPatches(strategy.Services, config)
genericApplyPatches(strategy.Deployments, config)
.
.
.
I'm just trying to think if there's a way to consolidate all the patching logic to this generate function rather than spreading it around.
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.
Yeah I think that makes sense, I have updated apply patches to be more generic so it only needs to be called for each resource type that we want to allow patches on
Don't want to creep in additional features, but I wonder if this would be applicable to virt-launchers as well? As we would like to add a sidecart with the libvirt_exporter (https://github.com/kumina/libvirt_exporter/), for example. |
Independent if that makes sense (probably does): We are exposing metrics for all VMIs through virt-handler, in case you are not aware of it. Let us know if you are missing something there. Have a look at https://kubevirt.io/user-guide/#/installation/monitoring?id=monitoring-kubevirt-components |
99c175f
to
5b2212c
Compare
It gets updated from this function since the correct install strategy will no longer exist |
23252b6
to
ac6b6b8
Compare
ac6b6b8
to
3ba675f
Compare
3ba675f
to
f1fdede
Compare
s := "CustomizeComponentsPatches" | ||
|
||
for _, p := range c.Patches { | ||
s += fmt.Sprintf("Resource%sName%sPatch%sType%s", p.ResourceType, p.ResourceName, p.Patch, string(p.Type)) |
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 that in this case using strings.StringBuilder
will be much more efficient.
Strings are immutable and for every patch we actually reallocate a new memory chunk and reference s
to the new location.
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.
code quality so far looks great! I have a couple of top level comments.
-
what happens (or should happen) if someone modifies the KubeVirt CR with a patch after install? It looks like we might ignore those changes today until the KubeVirt version is updated, then the patches would kick in?
-
i think this logic deserves a functional test case in tests/operator_test.go
@@ -335,6 +335,7 @@ func NewControllerDeployment(namespace string, repository string, imagePrefix st | |||
} | |||
|
|||
attachCertificateSecret(pod, VirtControllerCertSecretName, "/etc/virt-controller/certificates") | |||
|
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.
super minor, there's a random line added here to a file that otherwise has no changes.
To make everything react fast and easy to grasp I am still for doing the patches always when we load the install strategy and always just dump the plain shipped install strategy. That makes is absolutely clear and understandable what will happen: If patches are provided in the CR they are applied, if they are not there they are not. Of course that can be done by dumping the proper install strategy over and over, but it is mentally much more difficult to grasp and no questions like this will arise: If I roll back to the previous version which had patches and I don't provide the patches, will it still have them? You simply always get what we release + your patches on the CR. No exception. |
One additional note, after we merge the subresource PR, the |
/retest |
12 similar comments
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
/retest |
…figuration" The change causes constant failure when running focused tests [1], failing on [2]. Another issue the PR introduced has a proposed fix [3]. 1. https://github.com/kubevirt/kubevirt/blob/ bfe9df0/tests/vmi_networking_test.go#L677 2. https://github.com/kubevirt/kubevirt/blob/master/tests/utils.go#L2687 3. kubevirt#4143 This reverts commit 78f37c8, reversing changes made to 7b70b99.
…figuration" The change causes constant failure when running focused tests [1], failing on [2]. Another issue the PR introduced has a proposed fix [3]. 1. https://github.com/kubevirt/kubevirt/blob/ bfe9df0/tests/vmi_networking_test.go#L677 2. https://github.com/kubevirt/kubevirt/blob/master/tests/utils.go#L2687 3. kubevirt#4143 This reverts commit 78f37c8, reversing changes made to 7b70b99. Signed-off-by: Edward Haas <edwardh@redhat.com>
What this PR does / why we need it:
CustomizeComponents
field to the KubeVirt CRPatches
to be specifiedThis PR will allow users to customize the virt-controller, virt-handler, virt-api, and all other resources that are created by the virt-operator.
We need this to allow users to be able to customize the way kubevirt is ran in each of their environments. This gives users the power to specify where components can be scheduled, customizing flags and other use cases. If a user defines an invalid patch the operator will fail to deploy.
This current draft PR only adds this logic for the
virt-controller
. An example KubeVirt CR is as follows:Which issue(s) this PR fixes:
Fixes #3365
Special notes for your reviewer:
How do we feel able the name customizeComponents? I also ended up using the name
ComponentsCustomization
in the config struct. I think these two should be consistent, but would like opinions on what naming makes more sense?Is there any reason to continue passing individual arguments to functions such as
NewControllerDeployment
instead of passing the who config object?Release note: