Skip to content

Commit bd0915b

Browse files
committed
[core] Test kvStoreUnmarshalYAMLWithTags and YAML→workflow unmarshal
1 parent e5a6051 commit bd0915b

1 file changed

Lines changed: 263 additions & 0 deletions

File tree

core/workflow/role_test.go

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/AliceO2Group/Control/core/task/sm"
66
. "github.com/onsi/ginkgo/v2"
77
. "github.com/onsi/gomega"
8+
"gopkg.in/yaml.v3"
89
)
910

1011
func complexRoleTree() (root Role, leaves map[string]Role) {
@@ -254,4 +255,266 @@ var _ = Describe("role", func() {
254255
})
255256
})
256257
})
258+
259+
Describe("unmarshaling a YAML workflow template into a tree of roles", func() {
260+
Context("when the YAML template is a simple tree with a single task", func() {
261+
const yamlTemplate = `
262+
name: root_role
263+
description: description of the root role
264+
defaults:
265+
default1: "true"
266+
default2: value of default2
267+
default3: false
268+
vars:
269+
var1: "{{ default2 != 'none' }}"
270+
var2: "{{ default1 == 'true' && default3 == 'true' }}"
271+
var3: value of var3
272+
roles:
273+
- name: "first_role"
274+
enabled: "{{ default1 == 'true' }}"
275+
vars:
276+
var3: "{{ default2 }}"
277+
constraints:
278+
- attribute: some_attribute
279+
value: "{{ default2 }}"
280+
roles:
281+
- name: 'first_subrole'
282+
vars:
283+
var4: '{{default1 == "true" ? var3 : "value of var4"}}'
284+
task:
285+
load: name_of_task1
286+
- name: "second_subrole"
287+
enabled: 'false'
288+
roles:
289+
- name: "first_subsubrole"
290+
connect:
291+
- name: connection_name
292+
type: pull
293+
target: "{{ Up(2).Path }}.first_subrole:connection_name"
294+
rateLogging: "{{ default1 }}"
295+
task:
296+
load: name_of_task2
297+
- name: "second_role"
298+
call:
299+
func: testplugin.Noop()
300+
trigger: CONFIGURE
301+
timeout: 1s
302+
critical: false
303+
`
304+
role := new(aggregatorRole)
305+
306+
It("should unmarshal successfully", func() {
307+
err := yaml.Unmarshal([]byte(yamlTemplate), role)
308+
Expect(err).NotTo(HaveOccurred())
309+
})
310+
It("should create a tree with a task role and a call role", func() {
311+
Expect(role.GetName()).To(Equal("root_role"))
312+
Expect(role.GetRoles()).To(HaveLen(2))
313+
314+
Expect(role.GetRoles()[0].GetName()).To(Equal("first_role"))
315+
Expect(role.GetRoles()[0]).To(BeAssignableToTypeOf(&aggregatorRole{}))
316+
Expect(role.GetRoles()[0]).NotTo(BeAssignableToTypeOf(&callRole{}))
317+
Expect(role.GetRoles()[0].GetRoles()).To(HaveLen(2))
318+
319+
Expect(role.GetRoles()[0].GetRoles()[0].GetName()).To(Equal("first_subrole"))
320+
Expect(role.GetRoles()[0].GetRoles()[0]).To(BeAssignableToTypeOf(&taskRole{}))
321+
322+
Expect(role.GetRoles()[0].GetRoles()[1].GetName()).To(Equal("second_subrole"))
323+
Expect(role.GetRoles()[0].GetRoles()[1]).To(BeAssignableToTypeOf(&aggregatorRole{}))
324+
Expect(role.GetRoles()[0].GetRoles()[1].GetRoles()).To(HaveLen(1))
325+
326+
Expect(role.GetRoles()[0].GetRoles()[1].GetRoles()[0].GetName()).To(Equal("first_subsubrole"))
327+
Expect(role.GetRoles()[0].GetRoles()[1].GetRoles()[0]).To(BeAssignableToTypeOf(&taskRole{}))
328+
329+
Expect(role.GetRoles()[1].GetName()).To(Equal("second_role"))
330+
Expect(role.GetRoles()[1]).To(BeAssignableToTypeOf(&callRole{}))
331+
Expect(role.GetRoles()[1]).NotTo(BeAssignableToTypeOf(&taskRole{}))
332+
})
333+
It("should set the variables correctly", func() {
334+
Expect(role.GetDefaults().Raw()).To(HaveLen(3))
335+
Expect(role.GetRoles()[0].GetRoles()[0].GetVars().Raw()).To(HaveLen(1))
336+
Expect(role.GetRoles()[0].GetRoles()[1].GetVars().Raw()).To(HaveLen(0))
337+
Expect(role.GetRoles()[0].GetRoles()[0].ConsolidatedVarStack()).To(HaveLen(7))
338+
Expect(role.GetRoles()[0].GetRoles()[1].ConsolidatedVarStack()).To(HaveLen(6))
339+
Expect(role.GetRoles()[0].GetRoles()[0].GetVars().Raw()["var4"]).To(Equal("{{default1 == \"true\" ? var3 : \"value of var4\"}}"))
340+
})
341+
})
342+
343+
Context("when the YAML template resembles readout-dataflow", func() {
344+
const yamlTemplate = `
345+
name: !public readout-dataflow
346+
description: !public "Main workflow template for ALICE data taking"
347+
defaults:
348+
###############################
349+
# General Configuration Panel
350+
###############################
351+
dcs_enabled: !public
352+
value: "false"
353+
type: bool
354+
label: "DCS"
355+
description: "Enable/disable DCS SOR/EOR commands"
356+
widget: checkBox
357+
panel: General_Configuration
358+
index: 0
359+
dd_enabled: !public
360+
value: "true"
361+
type: bool
362+
label: "Data Distribution (FLP)"
363+
description: "Enable/disable Data Distribution components running on FLPs (StfBuilder and StfSender)"
364+
widget: checkBox
365+
panel: General_Configuration
366+
index: 1
367+
hosts: '["host1", "host2"]'
368+
vars:
369+
auto_stop_enabled: "{{ auto_stop_timeout != 'none' }}"
370+
ddsched_enabled: "{{ epn_enabled == 'true' && dd_enabled == 'true' }}"
371+
roles:
372+
###########################
373+
# Start of CTP Readout role
374+
###########################
375+
- name: "readout-ctp"
376+
enabled: "{{ ctp_readout_enabled == 'true' }}"
377+
vars:
378+
detector: "{{ctp_readout_enabled == 'true' ? inventory.DetectorForHost( ctp_readout_host ) : \"\" }}"
379+
readout_cfg_uri_standalone: "consul-ini://{{ consul_endpoint }}/o2/components/{{config.ResolvePath('readout/' + run_type + '/any/readout-standalone-' + ctp_readout_host)}}"
380+
readout_cfg_uri_stfb: "consul-ini://{{ consul_endpoint }}/o2/components/{{config.Resolve('readout', run_type, 'any', 'readout-stfb-' + ctp_readout_host)}}"
381+
dd_discovery_ib_hostname: "{{ ctp_readout_host }}-ib" # MUST be defined for all stfb and stfs
382+
# dpl_workflow is set to ctp_dpl_workflow
383+
dpl_workflow: "{{ util.PrefixedOverride( 'dpl_workflow', 'ctp' ) }}"
384+
dpl_command: "{{ util.PrefixedOverride( 'dpl_command', 'ctp' ) }}"
385+
stfs_shm_segment_size: "{{ ctp_stfs_shm_segment_size }}"
386+
it: "{{ ctp_readout_host }}"
387+
constraints:
388+
- attribute: machine_id
389+
value: "{{ ctp_readout_host }}"
390+
roles:
391+
- name: "readout"
392+
vars:
393+
readout_cfg_uri: '{{dd_enabled == "true" ? readout_cfg_uri_stfb : readout_cfg_uri_standalone}}'
394+
task:
395+
load: readout-ctp
396+
- name: "data-distribution"
397+
enabled: "{{dd_enabled == 'true' && (qcdd_enabled == 'false' && minimal_dpl_enabled == 'false' && dpl_workflow == 'none' && dpl_command == 'none')}}"
398+
roles:
399+
# stfb-standalone not supported on CTP machine
400+
# if ctp_readout_enabled, we also assume stfb_standalone is false
401+
- name: "stfb"
402+
vars:
403+
dd_discovery_stfb_id: stfb-{{ ctp_readout_host }}-{{ uid.New() }} # must be defined for all stfb roles
404+
connect:
405+
- name: readout
406+
type: pull
407+
target: "{{ Up(2).Path }}.readout:readout"
408+
rateLogging: "{{ fmq_rate_logging }}"
409+
task:
410+
load: stfbuilder-senderoutput
411+
- name: host-{{ it }}
412+
for:
413+
range: "{{ hosts }}"
414+
var: it
415+
vars:
416+
detector: "{{ inventory.DetectorForHost( it ) }}"
417+
readout_cfg_uri_standalone: "consul-ini://{{ consul_endpoint }}/o2/components/{{config.ResolvePath('readout/' + run_type + '/any/readout-standalone-' + it)}}"
418+
readout_cfg_uri_stfb: "consul-ini://{{ consul_endpoint }}/o2/components/{{config.Resolve('readout', run_type, 'any', 'readout-stfb-' + it)}}"
419+
dd_discovery_ib_hostname: "{{ it }}-ib" # MUST be defined for all stfb and stfs
420+
# dpl_workflow is set to <detector>_dpl_workflow if such an override exists
421+
dpl_workflow: "{{ util.PrefixedOverride( 'dpl_workflow', strings.ToLower( inventory.DetectorForHost( it ) ) ) }}"
422+
dpl_command: "{{ util.PrefixedOverride( 'dpl_command', strings.ToLower( inventory.DetectorForHost( it ) ) ) }}"
423+
constraints:
424+
- attribute: machine_id
425+
value: "{{ it }}"
426+
roles:
427+
- name: "readout"
428+
vars:
429+
readout_cfg_uri: '{{dd_enabled == "true" ? readout_cfg_uri_stfb : readout_cfg_uri_standalone}}'
430+
task:
431+
load: readout
432+
- name: dcs
433+
enabled: "{{dcs_enabled == 'true'}}"
434+
defaults:
435+
###############################
436+
# DCS Panel
437+
###############################
438+
dcs_detectors: "{{ detectors }}"
439+
dcs_sor_parameters: !public
440+
value: "{}"
441+
type: string
442+
label: "Global SOR parameters"
443+
description: "additional parameters for the DCS SOR"
444+
widget: editBox
445+
panel: DCS
446+
index: 2
447+
visibleif: $$dcs_enabled === "true"
448+
dcs_eor_parameters: !public
449+
value: "{}"
450+
type: string
451+
label: "Global EOR parameters"
452+
description: "additional parameters for the DCS EOR"
453+
widget: editBox
454+
panel: DCS
455+
index: 3
456+
visibleif: $$dcs_enabled === "true"
457+
roles:
458+
- name: pfr
459+
call:
460+
func: dcs.PrepareForRun()
461+
trigger: before_CONFIGURE
462+
await: after_CONFIGURE
463+
timeout: "{{ dcs_pfr_timeout }}"
464+
critical: false
465+
- name: sor
466+
call:
467+
func: dcs.StartOfRun()
468+
trigger: before_START_ACTIVITY
469+
timeout: "{{ dcs_sor_timeout }}"
470+
critical: true
471+
`
472+
role := new(aggregatorRole)
473+
474+
It("should unmarshal successfully", func() {
475+
err := yaml.Unmarshal([]byte(yamlTemplate), role)
476+
Expect(err).NotTo(HaveOccurred())
477+
})
478+
479+
It("should create a complex tree correctly", func() {
480+
Expect(role.GetName()).To(Equal("readout-dataflow"))
481+
Expect(role.GetRoles()).To(HaveLen(2)) // GetRoles excludes iterator roles
482+
Expect(role.Roles).To(HaveLen(3))
483+
Expect(role.GetRoles()[0].GetName()).To(Equal("readout-ctp"))
484+
485+
Expect(role.Roles[1].GetName()).To(Equal("host-{{ it }}"))
486+
Expect(role.Roles[1]).To(BeAssignableToTypeOf(&iteratorRole{}))
487+
488+
Expect(role.GetRoles()[1]).To(BeAssignableToTypeOf(&aggregatorRole{}))
489+
Expect(role.GetRoles()[1].GetRoles()).To(HaveLen(2))
490+
Expect(role.GetRoles()[1].GetRoles()[0]).To(BeAssignableToTypeOf(&callRole{}))
491+
})
492+
493+
It("should set the variables correctly", func() {
494+
Expect(role.GetDefaults().Raw()).To(HaveLen(3))
495+
Expect(role.GetRoles()[0].GetVars().Raw()).To(HaveLen(8))
496+
Expect(role.Roles[1].GetVars().Raw()).To(HaveLen(6))
497+
Expect(role.GetRoles()[1].GetVars().Raw()).To(HaveLen(0))
498+
499+
// CTP subtree
500+
cvs, err := role.GetRoles()[0].GetRoles()[1].GetRoles()[0].ConsolidatedVarStack()
501+
Expect(err).NotTo(HaveOccurred())
502+
Expect(cvs).To(HaveLen(14))
503+
504+
Expect(cvs["dd_enabled"]).To(Equal("true"))
505+
Expect(cvs["readout_cfg_uri_stfb"]).To(Equal("consul-ini://{{ consul_endpoint }}/o2/components/{{config.Resolve('readout', run_type, 'any', 'readout-stfb-' + ctp_readout_host)}}"))
506+
Expect(cvs["dd_discovery_ib_hostname"]).To(Equal("{{ ctp_readout_host }}-ib"))
507+
Expect(cvs["ddsched_enabled"]).To(Equal("{{ epn_enabled == 'true' && dd_enabled == 'true' }}"))
508+
509+
// DCS subtree
510+
cvs, err = role.GetRoles()[1].GetRoles()[0].ConsolidatedVarStack()
511+
Expect(err).NotTo(HaveOccurred())
512+
Expect(cvs).To(HaveLen(8))
513+
514+
Expect(cvs["dcs_enabled"]).To(Equal("false"))
515+
Expect(cvs["dcs_detectors"]).To(Equal("{{ detectors }}"))
516+
Expect(cvs["dcs_sor_parameters"]).To(Equal("{}"))
517+
})
518+
})
519+
})
257520
})

0 commit comments

Comments
 (0)