Skip to content

Commit 5a9033c

Browse files
authored
Merge pull request #168 from kstrenkova/merge-workflow-section-in-webhook
Refactor merging of workflow section
2 parents 19ed9f0 + bae75ae commit 5a9033c

10 files changed

Lines changed: 128 additions & 265 deletions

.zuul.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@
8686
tempestRun:
8787
includeList: |
8888
tempest.api.compute.admin.test_flavors.FlavorsAdminTestJSON.test_create_flavor_using_string_ram
89+
concurrency: 8
90+
tempestconfRun:
91+
collectTiming: true
92+
8993
cifmw_test_operator_tempest_extra_images:
9094
- URL: https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img
9195
name: cirros-0.6.2-test-operator

api/v1beta1/ansibletest_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ type AnsibleTestSpec struct {
9999
}
100100

101101
type AnsibleTestWorkflowSpec struct {
102-
WorkflowCommonParameters `json:",inline"`
103-
CommonOpenstackConfig `json:",inline"`
102+
WorkflowCommonOptions `json:",inline"`
103+
CommonOpenstackConfig `json:",inline"`
104104

105105
// +operator-sdk:csv:customresourcedefinitions:type=spec
106106
// +kubebuilder:validation:Required

api/v1beta1/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ type CommonTestStatus struct {
133133
NetworkAttachments map[string][]string `json:"networkAttachments,omitempty"`
134134
}
135135

136-
type WorkflowCommonParameters struct {
136+
type WorkflowCommonOptions struct {
137137
// +operator-sdk:csv:customresourcedefinitions:type=spec
138138
// +kubebuilder:validation:optional
139139
// +optional

api/v1beta1/tempest_types_workflow.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,8 @@ type WorkflowTempestconfRunSpec struct {
227227
// TempestSpec - configuration of execution of tempest. For specific configuration
228228
// of tempest see TempestRunSpec and for discover-tempest-config see TempestconfRunSpec.
229229
type WorkflowTempestSpec struct {
230-
WorkflowCommonParameters `json:",inline"`
231-
CommonOpenstackConfig `json:",inline"`
230+
WorkflowCommonOptions `json:",inline"`
231+
CommonOpenstackConfig `json:",inline"`
232232

233233
// The desired amount of resources that should be assigned to each test pod
234234
// spawned using the Tempest CR. https://pkg.go.dev/k8s.io/api/core/v1#ResourceRequirements

api/v1beta1/tobiko_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ type TobikoSpec struct {
119119
}
120120

121121
type TobikoWorkflowSpec struct {
122-
WorkflowCommonParameters `json:",inline"`
122+
WorkflowCommonOptions `json:",inline"`
123123

124124
// +kubebuilder:default:={limits: {cpu: "8000m", memory: "8Gi"}, requests: {cpu: "4000m", memory: "4Gi"}}
125125
// The desired amount of resources that should be assigned to each test pod

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controllers/ansibletest_controller.go

Lines changed: 15 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,12 @@ import (
2222
"fmt"
2323
"strconv"
2424

25-
"reflect"
26-
2725
"github.com/go-logr/logr"
2826
"github.com/openstack-k8s-operators/lib-common/modules/common"
2927
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
3028
"github.com/openstack-k8s-operators/lib-common/modules/common/env"
3129
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
3230
testv1beta1 "github.com/openstack-k8s-operators/test-operator/api/v1beta1"
33-
v1beta1 "github.com/openstack-k8s-operators/test-operator/api/v1beta1"
3431
"github.com/openstack-k8s-operators/test-operator/pkg/ansibletest"
3532
corev1 "k8s.io/api/core/v1"
3633
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
@@ -129,6 +126,9 @@ func (r *AnsibleTestReconciler) Reconcile(ctx context.Context, req ctrl.Request)
129126

130127
workflowLength := len(instance.Spec.Workflow)
131128
nextAction, nextWorkflowStep, err := r.NextAction(ctx, instance, workflowLength)
129+
if nextWorkflowStep < workflowLength {
130+
MergeSections(&instance.Spec, instance.Spec.Workflow[nextWorkflowStep])
131+
}
132132

133133
switch nextAction {
134134
case Failure:
@@ -206,32 +206,14 @@ func (r *AnsibleTestReconciler) Reconcile(ctx context.Context, req ctrl.Request)
206206
// Create a new pod
207207
mountCerts := r.CheckSecretExists(ctx, instance, "combined-ca-bundle")
208208
podName := r.GetPodName(instance, nextWorkflowStep)
209-
envVars, workflowOverrideParams := r.PrepareAnsibleEnv(instance, nextWorkflowStep)
209+
envVars, workflowOverrideParams := r.PrepareAnsibleEnv(instance)
210210
logsPVCName := r.GetPVCLogsName(instance, 0)
211211
containerImage, err := r.GetContainerImage(ctx, workflowOverrideParams["ContainerImage"], instance)
212-
privileged := r.OverwriteAnsibleWithWorkflow(instance.Spec, "Privileged", "pbool", nextWorkflowStep).(bool)
212+
privileged := instance.Spec.Privileged
213213
if err != nil {
214214
return ctrl.Result{}, err
215215
}
216216

217-
if nextWorkflowStep < len(instance.Spec.Workflow) {
218-
if instance.Spec.Workflow[nextWorkflowStep].NodeSelector != nil {
219-
instance.Spec.NodeSelector = *instance.Spec.Workflow[nextWorkflowStep].NodeSelector
220-
}
221-
222-
if instance.Spec.Workflow[nextWorkflowStep].Tolerations != nil {
223-
instance.Spec.Tolerations = *instance.Spec.Workflow[nextWorkflowStep].Tolerations
224-
}
225-
226-
if instance.Spec.Workflow[nextWorkflowStep].SELinuxLevel != nil {
227-
instance.Spec.SELinuxLevel = *instance.Spec.Workflow[nextWorkflowStep].SELinuxLevel
228-
}
229-
230-
if instance.Spec.Workflow[nextWorkflowStep].Resources != nil {
231-
instance.Spec.Resources = *instance.Spec.Workflow[nextWorkflowStep].Resources
232-
}
233-
}
234-
235217
podDef := ansibletest.Pod(
236218
instance,
237219
serviceLabels,
@@ -284,82 +266,32 @@ func (r *AnsibleTestReconciler) SetupWithManager(mgr ctrl.Manager) error {
284266
Complete(r)
285267
}
286268

287-
func (r *Reconciler) OverwriteAnsibleWithWorkflow(
288-
instance v1beta1.AnsibleTestSpec,
289-
sectionName string,
290-
workflowValueType string,
291-
workflowStepNum int,
292-
) interface{} {
293-
if len(instance.Workflow)-1 < workflowStepNum {
294-
reflected := reflect.ValueOf(instance)
295-
fieldValue := reflected.FieldByName(sectionName)
296-
return fieldValue.Interface()
297-
}
298-
299-
reflected := reflect.ValueOf(instance)
300-
SpecValue := reflected.FieldByName(sectionName).Interface()
301-
302-
reflected = reflect.ValueOf(instance.Workflow[workflowStepNum])
303-
WorkflowValue := reflected.FieldByName(sectionName).Interface()
304-
305-
if workflowValueType == "pbool" {
306-
if val, ok := WorkflowValue.(*bool); ok && val != nil {
307-
return *(WorkflowValue.(*bool))
308-
}
309-
return SpecValue.(bool)
310-
} else if workflowValueType == "puint8" {
311-
if val, ok := WorkflowValue.(*uint8); ok && val != nil {
312-
return *(WorkflowValue.(*uint8))
313-
}
314-
return SpecValue
315-
} else if workflowValueType == "string" {
316-
if val, ok := WorkflowValue.(string); ok && val != "" {
317-
return WorkflowValue
318-
}
319-
return SpecValue
320-
}
321-
322-
return nil
323-
}
324-
325269
// This function prepares env variables for a single workflow step.
326270
func (r *AnsibleTestReconciler) PrepareAnsibleEnv(
327271
instance *testv1beta1.AnsibleTest,
328-
step int,
329272
) (map[string]env.Setter, map[string]string) {
330273
// Prepare env vars
331274
envVars := make(map[string]env.Setter)
332275
workflowOverrideParams := make(map[string]string)
333276

334277
// volumes workflow override
335-
workflowOverrideParams["WorkloadSSHKeySecretName"] = r.OverwriteAnsibleWithWorkflow(instance.Spec, "WorkloadSSHKeySecretName", "string", step).(string)
336-
workflowOverrideParams["ComputesSSHKeySecretName"] = r.OverwriteAnsibleWithWorkflow(instance.Spec, "ComputesSSHKeySecretName", "string", step).(string)
337-
workflowOverrideParams["ContainerImage"] = r.OverwriteAnsibleWithWorkflow(instance.Spec, "ContainerImage", "string", step).(string)
278+
workflowOverrideParams["WorkloadSSHKeySecretName"] = instance.Spec.WorkloadSSHKeySecretName
279+
workflowOverrideParams["ComputesSSHKeySecretName"] = instance.Spec.ComputesSSHKeySecretName
280+
workflowOverrideParams["ContainerImage"] = instance.Spec.ContainerImage
338281

339282
// bool
340-
debug := r.OverwriteAnsibleWithWorkflow(instance.Spec, "Debug", "pbool", step).(bool)
283+
debug := instance.Spec.Debug
341284
if debug {
342285
envVars["POD_DEBUG"] = env.SetValue("true")
343286
}
344287

345288
// strings
346-
extraVars := r.OverwriteAnsibleWithWorkflow(instance.Spec, "AnsibleExtraVars", "string", step).(string)
347-
envVars["POD_ANSIBLE_EXTRA_VARS"] = env.SetValue(extraVars)
348-
349-
extraVarsFile := r.OverwriteAnsibleWithWorkflow(instance.Spec, "AnsibleVarFiles", "string", step).(string)
350-
envVars["POD_ANSIBLE_FILE_EXTRA_VARS"] = env.SetValue(extraVarsFile)
351-
352-
inventory := r.OverwriteAnsibleWithWorkflow(instance.Spec, "AnsibleInventory", "string", step).(string)
353-
envVars["POD_ANSIBLE_INVENTORY"] = env.SetValue(inventory)
354-
355-
gitRepo := r.OverwriteAnsibleWithWorkflow(instance.Spec, "AnsibleGitRepo", "string", step).(string)
356-
envVars["POD_ANSIBLE_GIT_REPO"] = env.SetValue(gitRepo)
357-
358-
playbookPath := r.OverwriteAnsibleWithWorkflow(instance.Spec, "AnsiblePlaybookPath", "string", step).(string)
359-
envVars["POD_ANSIBLE_PLAYBOOK"] = env.SetValue(playbookPath)
360-
361-
ansibleCollections := r.OverwriteAnsibleWithWorkflow(instance.Spec, "AnsibleCollections", "string", step).(string)
362-
envVars["POD_INSTALL_COLLECTIONS"] = env.SetValue(ansibleCollections)
289+
envVars["POD_ANSIBLE_EXTRA_VARS"] = env.SetValue(instance.Spec.AnsibleExtraVars)
290+
envVars["POD_ANSIBLE_FILE_EXTRA_VARS"] = env.SetValue(instance.Spec.AnsibleVarFiles)
291+
envVars["POD_ANSIBLE_INVENTORY"] = env.SetValue(instance.Spec.AnsibleInventory)
292+
envVars["POD_ANSIBLE_GIT_REPO"] = env.SetValue(instance.Spec.AnsibleGitRepo)
293+
envVars["POD_ANSIBLE_PLAYBOOK"] = env.SetValue(instance.Spec.AnsiblePlaybookPath)
294+
envVars["POD_INSTALL_COLLECTIONS"] = env.SetValue(instance.Spec.AnsibleCollections)
363295

364296
return envVars, workflowOverrideParams
365297
}

controllers/common.go

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -611,44 +611,6 @@ func (r *Reconciler) setConfigOverwrite(customData map[string]string, configOver
611611
}
612612
}
613613

614-
func (r *Reconciler) OverwriteValueWithWorkflow(
615-
instance v1beta1.TobikoSpec,
616-
sectionName string,
617-
workflowValueType string,
618-
workflowStepNum int,
619-
) interface{} {
620-
if len(instance.Workflow)-1 < workflowStepNum {
621-
reflected := reflect.ValueOf(instance)
622-
fieldValue := reflected.FieldByName(sectionName)
623-
return fieldValue.Interface()
624-
}
625-
626-
reflected := reflect.ValueOf(instance)
627-
tobikoSpecValue := reflected.FieldByName(sectionName).Interface()
628-
629-
reflected = reflect.ValueOf(instance.Workflow[workflowStepNum])
630-
tobikoWorkflowValue := reflected.FieldByName(sectionName).Interface()
631-
632-
if workflowValueType == "pbool" {
633-
if val, ok := tobikoWorkflowValue.(*bool); ok && val != nil {
634-
return *(tobikoWorkflowValue.(*bool))
635-
}
636-
return tobikoSpecValue.(bool)
637-
} else if workflowValueType == "puint8" {
638-
if val, ok := tobikoWorkflowValue.(*uint8); ok && val != nil {
639-
return *(tobikoWorkflowValue.(*uint8))
640-
}
641-
return tobikoSpecValue
642-
} else if workflowValueType == "string" {
643-
if val, ok := tobikoWorkflowValue.(string); ok && val != "" {
644-
return tobikoWorkflowValue
645-
}
646-
return tobikoSpecValue
647-
}
648-
649-
return nil
650-
}
651-
652614
func GetCommonRbacRules(privileged bool) []rbacv1.PolicyRule {
653615
rbacPolicyRule := rbacv1.PolicyRule{
654616
APIGroups: []string{"security.openshift.io"},
@@ -734,3 +696,46 @@ func EnsureCloudsConfigMapExists(
734696

735697
return ctrl.Result{}, nil
736698
}
699+
700+
func IsEmpty(value interface{}) bool {
701+
if v, ok := value.(reflect.Value); ok {
702+
switch v.Kind() {
703+
case reflect.String, reflect.Map:
704+
return v.Len() == 0
705+
case reflect.Ptr, reflect.Interface, reflect.Slice:
706+
return v.IsNil()
707+
}
708+
}
709+
return false
710+
}
711+
712+
// MergeSections iterates through all CR parameters and overrides them
713+
// with non-empty values from the workflow section of the current step.
714+
func MergeSections(main interface{}, workflow interface{}) {
715+
mReflect := reflect.ValueOf(main).Elem()
716+
wReflect := reflect.ValueOf(workflow)
717+
718+
for i := 0; i < mReflect.NumField(); i++ {
719+
name := mReflect.Type().Field(i).Name
720+
mValue := mReflect.Field(i)
721+
wValue := wReflect.FieldByName(name)
722+
723+
if mValue.Kind() == reflect.Struct && wValue.Kind() != reflect.Ptr {
724+
switch name {
725+
case "CommonOptions":
726+
wValue := wReflect.FieldByName("WorkflowCommonOptions")
727+
MergeSections(mValue.Addr().Interface(), wValue.Interface())
728+
case "TempestRun", "TempestconfRun":
729+
MergeSections(mValue.Addr().Interface(), wValue.Interface())
730+
}
731+
continue
732+
}
733+
734+
if wValue.IsValid() && !IsEmpty(wValue) {
735+
if wValue.Kind() == reflect.Ptr && mValue.Kind() != reflect.Ptr {
736+
wValue = wValue.Elem()
737+
}
738+
mValue.Set(wValue)
739+
}
740+
}
741+
}

0 commit comments

Comments
 (0)