11/*
22 * === This file is part of ALICE O² ===
33 *
4- * Copyright 2018 CERN and copyright holders of ALICE O².
4+ * Copyright 2018-2020 CERN and copyright holders of ALICE O².
55 * Author: Teo Mrnjavac <teo.mrnjavac@cern.ch>
66 *
77 * This program is free software: you can redistribute it and/or modify
@@ -26,9 +26,9 @@ package workflow
2626
2727import (
2828 "errors"
29+
2930 "github.com/AliceO2Group/Control/common/gera"
3031 "github.com/AliceO2Group/Control/core/repos"
31- "strconv"
3232
3333 "github.com/AliceO2Group/Control/core/task"
3434 "github.com/AliceO2Group/Control/core/task/constraint"
@@ -37,7 +37,7 @@ import (
3737
3838type iteratorRole struct {
3939 aggregator
40- For iteratorInfo `yaml:"for,omitempty"`
40+ For iteratorRange `yaml:"for,omitempty"`
4141 template roleTemplate
4242}
4343
@@ -55,14 +55,46 @@ func (i *iteratorRole) UnmarshalYAML(unmarshal func(interface{}) error) (err err
5555 if err != nil {
5656 return
5757 }
58- auxFor := struct {
59- For iteratorInfo `yaml:"for"`
58+
59+ type _iteratorRangeUnion struct {
60+ Begin * string `yaml:"begin"`
61+ End * string `yaml:"end"`
62+ Var * string `yaml:"var"`
63+ Range * string `yaml:"range"`
64+ }
65+ auxForUnion := struct {
66+ For _iteratorRangeUnion `yaml:"for"`
6067 }{}
61- err = unmarshal (& auxFor )
68+ err = unmarshal (& auxForUnion )
6269 if err != nil {
6370 return
6471 }
6572
73+ var forBlock iteratorRange
74+ switch {
75+ case auxForUnion .For .Begin != nil && auxForUnion .For .End != nil && auxForUnion .For .Var != nil :
76+ auxFor := struct {
77+ For * iteratorRangeFor `yaml:"for"`
78+ }{}
79+ err = unmarshal (& auxFor )
80+ if err != nil {
81+ return
82+ }
83+ forBlock = auxFor .For
84+ case auxForUnion .For .Range != nil && auxForUnion .For .Var != nil :
85+ auxFor := struct {
86+ For * iteratorRangeExpr `yaml:"for"`
87+ }{}
88+ err = unmarshal (& auxFor )
89+ if err != nil {
90+ return
91+ }
92+ forBlock = auxFor .For
93+ default :
94+ err = errors .New ("invalid range specifier in iterator" )
95+ return
96+ }
97+
6698 var template roleTemplate
6799 switch {
68100 case auxUnion .Roles != nil && auxUnion .Task == nil :
@@ -79,47 +111,13 @@ func (i *iteratorRole) UnmarshalYAML(unmarshal func(interface{}) error) (err err
79111 }
80112
81113 role .template = template
82- role .For = auxFor . For
114+ role .For = forBlock
83115
84116 // FIXME: if Name does not contain {{ }}, we must bail!
85-
86- err = role .expandTemplate ()
87- if err != nil {
88- return
89- }
90117 * i = role
91118 return
92119}
93120
94- type iteratorInfo struct {
95- Begin int `yaml:"begin"`
96- End int `yaml:"end"`
97- Var string `yaml:"var"`
98- }
99-
100- func (f * iteratorInfo ) UnmarshalYAML (unmarshal func (interface {}) error ) (err error ) {
101- aux := struct {
102- Begin string `yaml:"begin"`
103- End string `yaml:"end"`
104- Var string `yaml:"var"`
105- }{}
106- err = unmarshal (& aux )
107- if err != nil {
108- return
109- }
110-
111- f .Begin , err = strconv .Atoi (aux .Begin )
112- if err != nil {
113- return
114- }
115- f .End , err = strconv .Atoi (aux .End )
116- if err != nil {
117- return
118- }
119- f .Var = aux .Var
120- return
121- }
122-
123121func (i * iteratorRole ) GlobFilter (g glob.Glob ) (rs []Role ) {
124122 rs = make ([]Role , 0 )
125123 for _ , chr := range i .Roles {
@@ -136,6 +134,11 @@ func (i *iteratorRole) ProcessTemplates(workflowRepo *repos.Repo) (err error) {
136134 return errors .New ("role tree error when processing templates" )
137135 }
138136
137+ err = i .expandTemplate ()
138+ if err != nil {
139+ return
140+ }
141+
139142 for _ , role := range i .Roles {
140143 err = role .ProcessTemplates (workflowRepo )
141144 if err != nil {
@@ -146,14 +149,28 @@ func (i *iteratorRole) ProcessTemplates(workflowRepo *repos.Repo) (err error) {
146149}
147150
148151func (i * iteratorRole ) expandTemplate () (err error ) {
149- values := make (map [string ]string )
152+ varStack := make (map [string ]string )
153+ if parent := i .GetParent (); parent != nil {
154+ varStack , _ = gera .FlattenStack (
155+ parent .GetDefaults (),
156+ parent .GetVars (),
157+ parent .GetUserVars (),
158+ )
159+ }
150160
151161 roles := make ([]Role , 0 )
152162
153- for j := i .For .Begin ; j <= i .For .End ; j ++ {
154- values [i .For .Var ] = strconv .Itoa (j )
163+ var ran []string
164+ ran , err = i .For .GetRange (varStack )
165+ if err != nil {
166+ return
167+ }
168+
169+ for _ , localValue := range ran {
170+ locals := make (map [string ]string )
171+ locals [i .For .GetVar ()] = localValue
155172 var newRole Role
156- newRole , err = i .template .generateRole (values )
173+ newRole , err = i .template .generateRole (locals )
157174 if err != nil {
158175 return
159176 }
0 commit comments