in workflow.go [460:557]
func (w *Workflow) populate(ctx context.Context) DError {
for k, v := range w.Vars {
if v.Required && v.Value == "" {
return Errf("cannot populate workflow, required var %q is unset", k)
}
}
// Set some generic autovars and run first round of var substitution.
cwd, _ := os.Getwd()
now := time.Now().UTC()
w.username = getUser()
w.autovars = map[string]string{
"ID": w.id,
"DATE": now.Format("20060102"),
"DATETIME": now.Format("20060102150405"),
"TIMESTAMP": strconv.FormatInt(now.Unix(), 10),
"USERNAME": w.username,
"WFDIR": w.workflowDir,
"CWD": cwd,
}
var replacements []string
for k, v := range w.autovars {
replacements = append(replacements, fmt.Sprintf("${%s}", k), v)
}
for k, v := range w.Vars {
replacements = append(replacements, fmt.Sprintf("${%s}", k), v.Value)
}
substitute(reflect.ValueOf(w).Elem(), strings.NewReplacer(replacements...))
// Parse timeout.
timeout, err := time.ParseDuration(w.DefaultTimeout)
if err != nil {
return Errf("failed to parse timeout for workflow: %v", err)
}
w.defaultTimeout = timeout
// Set up GCS paths.
if w.GCSPath == "" {
dBkt, err := daisyBkt(ctx, w.StorageClient, w.Project)
if err != nil {
return err
}
w.GCSPath = "gs://" + dBkt
}
bkt, p, derr := splitGCSPath(w.GCSPath)
if derr != nil {
return derr
}
w.bucket = bkt
w.scratchPath = path.Join(p, fmt.Sprintf("daisy-%s-%s-%s", w.Name, now.Format("20060102-15:04:05"), w.id))
w.sourcesPath = path.Join(w.scratchPath, "sources")
w.logsPath = path.Join(w.scratchPath, "logs")
w.outsPath = path.Join(w.scratchPath, "outs")
// Generate more autovars from workflow fields. Run second round of var substitution.
w.autovars["NAME"] = w.Name
w.autovars["FULLNAME"] = w.genName("")
w.autovars["ZONE"] = w.Zone
w.autovars["PROJECT"] = w.Project
w.autovars["GCSPATH"] = w.GCSPath
w.autovars["SCRATCHPATH"] = fmt.Sprintf("gs://%s/%s", w.bucket, w.scratchPath)
w.autovars["SOURCESPATH"] = fmt.Sprintf("gs://%s/%s", w.bucket, w.sourcesPath)
w.autovars["LOGSPATH"] = fmt.Sprintf("gs://%s/%s", w.bucket, w.logsPath)
w.autovars["OUTSPATH"] = fmt.Sprintf("gs://%s/%s", w.bucket, w.outsPath)
replacements = []string{}
for k, v := range w.autovars {
replacements = append(replacements, fmt.Sprintf("${%s}", k), v)
}
substitute(reflect.ValueOf(w).Elem(), strings.NewReplacer(replacements...))
if w.Logger == nil {
w.createLogger(ctx)
}
// Run populate on each step.
for name, s := range w.Steps {
s.name = name
s.w = w
if err := w.populateStep(ctx, s); err != nil {
return Errf("error populating step %q: %v", name, err)
}
}
// We do this here, and not in validate, as embedded startup scripts could
// have what we think are daisy variables.
if err := w.validateVarsSubbed(); err != nil {
return err
}
if err := w.substituteSourceVars(ctx, reflect.ValueOf(w).Elem()); err != nil {
return err
}
return nil
}