-
Notifications
You must be signed in to change notification settings - Fork 20
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
Move merging of workflow section into webhook #168
base: main
Are you sure you want to change the base?
Move merging of workflow section into webhook #168
Conversation
Skipping CI for Draft Pull Request. |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: kstrenkova The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
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.
@kstrenkova, this is really nice progress! 🎉 I say we schedule a call and discuss details but generally speaking I think we can make this work. I've just tried to test this locally. I had to make some minor tweaks (see comments) for the merging to work on the TempestRun
section on my machine.
Anyway, really good job! 👍 Even when you do not manage to finish this task and somebody will be working on it instead of you then you still laid a really good foundation here!
From our last conversation I was under the impression that this won't work. I think this will still require 2 - 3 PR updates and reviews but it is on a good path.
controllers/tempest_controller.go
Outdated
func getTempestRun(instance *testv1beta1.Tempest, workflowStepNum int) testv1beta1.TempestRunSpec { | ||
if workflowStepNum < len(instance.Spec.Workflow) { | ||
wtRun := instance.Spec.Workflow[workflowStepNum].TempestRun | ||
tRun := changeType(wtRun) | ||
return tRun | ||
} | ||
return instance.Spec.TempestRun | ||
} | ||
|
||
func changeType(wtRun testv1beta1.WorkflowTempestRunSpec) testv1beta1.TempestRunSpec { | ||
var tRun testv1beta1.TempestRunSpec | ||
|
||
wtReflected := reflect.ValueOf(wtRun) | ||
tReflected := reflect.ValueOf(&tRun).Elem() | ||
|
||
for i := 0; i < wtReflected.NumField(); i++ { | ||
tName := tReflected.Type().Field(i).Name | ||
tValue := tReflected.Field(i) | ||
|
||
wtValue := wtReflected.FieldByName(tName) | ||
if !wtValue.IsNil() { | ||
wtValue = wtValue.Elem() | ||
tValue.Set(wtValue) | ||
} | ||
} | ||
return tRun | ||
} |
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.
Nice solution! 🥳
I'm wondering whether we can bypass this somehow. I'm thinking about getting rid of the pointers entirely. But this can be a little bit tricky.
But even if we do not make the workflows work without the pointers then I think that calling a slight modification of this function at the beginning of the reconcile loop won't hurt.
Again, we can make this little bit more generic:).
controllers/tempest_controller.go
Outdated
return instance.Spec.TempestRun | ||
} | ||
|
||
func changeType(wtRun testv1beta1.WorkflowTempestRunSpec) testv1beta1.TempestRunSpec { |
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 should aim at making this function more generic by replacing the types with interface{}
. The caller of the function will be responsible of casting the result to a correct type.
func changeType(wtRun testv1beta1.WorkflowTempestRunSpec) testv1beta1.TempestRunSpec { | |
func changeType(instance interface{}) instance interface{} { |
e880a74
to
af17dde
Compare
Currently, the merging of workflow section is done in controllers of related CRs. We want to move the merging logic into webhooks to make the process cleaner.
af17dde
to
6b1c12c
Compare
I have added a new version of this patch that can also work with structures by calling the function for adding values from TempestRun section recursively. There is maybe needed a bit more generalization to get the functions working for all resources, but for Tempest this version should work. |
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 the PR is moving in the right direction. Nice work! 👍
I've added couple of comments @kstrenkova. Let me know what you think:).
tRunValue := src.Field(i) | ||
wtRunValue := dest.FieldByName(tRunName) | ||
|
||
if wtRunValue.IsZero() && !tRunValue.IsZero() { |
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 use of IsZero()
function is not 100 % accurate here because IsZero()
returns true
when variable e.g. concurrency
is set to 0
[1].
What do you think @kstrenkova about this? Would it be a problem?
if wtRunValue.IsZero() && !tRunValue.IsZero() { | |
if wtRunValue.IsNil() { |
You can also use wtRunValue.IsZero()
it is an equivalent to wtRunValue.IsNil()
when wtRunValue is a pointer.
[1] https://cs.opensource.google/go/go/+/refs/tags/go1.23.2:src/reflect/value.go;l=1572
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.
Nice catch, I think the need for !tRunValue.IsNil
is still there though 🤔 The problem was that if the value in tempestRun was nil, it would create an error.
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.
Yes, you are right:
The Tempest "tempest-tests" is invalid:
* spec.workflow[0].tempestRun.extraImagesType: Invalid value: "null": spec.workflow[0].tempestRun.extraImagesType in body must be of type array: "null"
* spec.workflow[0].tempestRun.externalPlugin: Invalid value: "null": spec.workflow[0].tempestRun.externalPlugin in body must be of type array: "null"
* spec.workflow[0].tempestRun.extraRPMs: Invalid value: "null": spec.workflow[0].tempestRun.extraRPMs in body must be of type array: "null"
Notice that the error only impacts arrays. We are trying to assign null to what should be a pointer to an array. Is there a way how to fix this? What about checking whether the array is empty in the tRun section and if it is then do not perform the assignment?
@@ -28,3 +33,42 @@ const ( | |||
"ensures that the copying of the logs to the PV is completed without any " + | |||
"complications." | |||
) | |||
|
|||
// merge non-workflow section into workflow | |||
func mergeSectionIntoWorkflow(instance interface{}, workflowStepNum 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.
I would modify the interface of this function like this:
func mergeSectionIntoWorkflow(instance interface{}, workflowStepNum int) { | |
func mergeSectionIntoWorkflow(instance interface{}, instanceWorkflowSection {}interface) { |
It would be a responsibility of the webhook to pass the correct values. Wdyt?:)
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 looked into it and I don't understand why this would be needed 😄 Could you please explain your thought behind it a bit more?
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.
Ok, so the idea for this function is to be generic because it is inside of the commonw_webhook.go
. It should work for Tempest, Tobiko, HorizonTest and AnsibleTest CR. Yet you have a code which is specific to Tempest CR inside the function [1].
The idea is that inside the webhook you would call this function like this:
if len(spec.Workflow) > 0 {
for _, workflowStepSpec := range spec.Workflow {
mergeSectionIntoWorkflow(spec, workflowStepSpec)
}
}
This would allow you to avoid the need to cast the instance variable to TempestSpec before you can grab the workflow section.
[1] here
} | ||
|
||
func changeType(instance interface{}, workflowStepNum int) interface{} { | ||
// TODO other types; else if typedInstance, ok := instance.(*v1beta1.HorizonTest); |
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.
Yes, I agree:)
@@ -550,3 +550,38 @@ func GetCommonRbacRules(privileged bool) []rbacv1.PolicyRule { | |||
|
|||
return []rbacv1.PolicyRule{rbacPolicyRule} | |||
} | |||
|
|||
// TODO make general for all resources |
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.
👍
tRun := spec.TempestRun | ||
wtRun := &spec.Workflow[workflowStepNum].TempestRun |
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.
We can start the copying of the non-workflow values directly from Spec.
. I know it was not done like so up until now for Tempest CR. The long term goal is to unify the behavior of the CRs so it would be nice to keep it consistent with the rest of them (like tobiko, ansibletest, ...).
tRun := spec.TempestRun | |
wtRun := &spec.Workflow[workflowStepNum].TempestRun | |
tRun := spec | |
wtRun := &spec.Workflow[workflowStepNum] |
It might require some changes here:) [1].
Also, we should add similar behavior for the TempestconfRunSpec
.
Currently, the merging of workflow section is done in controllers of related CRs. We want to move the merging logic into webhooks to make the process cleaner.
Depends on: #160