func dumpTemplate()

in internal/tfengine/tfengine.go [157:251]


func dumpTemplate(conf *Config, pwd, cacheDir, outputPath string, ti *templateInfo) error {
	outputPath = filepath.Join(outputPath, ti.OutputPath)

	data, err := template.CopyData(conf.Data)
	if err != nil {
		return err
	}

	// Make the schema available.
	trimDescriptions(conf.Schema)
	data["__schema__"] = conf.Schema

	flattenedData, err := template.FlattenData(data, ti.Flatten)
	if err != nil {
		return err
	}
	// Merge flattened data into template data so that it gets checked by the schema check later.
	if err := template.MergeData(ti.Data, flattenedData); err != nil {
		return err
	}
	if err := template.MergeData(data, ti.Data); err != nil {
		return err
	}

	// Pass through keys that should be validated against the schema.
	// Don't do error checking if keys are missing, instead let schemas
	// in the child templates do the validation.
	for _, k := range ti.Passthrough {
		if v, ok := conf.Data[k]; ok {
			ti.Data[k] = v
		}
	}

	switch {
	case ti.RecipePath != "":
		rp, err := fileutil.Fetch(ti.RecipePath, pwd, cacheDir)
		if err != nil {
			return err
		}
		rc, err := loadConfig(rp, data)
		if err != nil {
			return fmt.Errorf("load recipe %q: %v", rp, err)
		}

		compat, err := version.IsCompatible(rc.Version)
		if err != nil {
			return err
		}
		if !compat {
			return fmt.Errorf("binary version %v incompatible with template version constraint %v in %v", cmd.Version, rc.Version, rp)
		}

		// Validate the schema, if present.
		if len(rc.Schema) > 0 {
			// Only check against unmerged template data so we can disallow additional properties in the schema.
			if err := jsonschema.ValidateMap(rc.Schema, ti.Data); err != nil {
				return fmt.Errorf("recipe %q: %v", rp, err)
			}
		}

		// Each recipe could have a top-level data block. Keep it and merge, instead of overrwriting.
		if err := template.MergeData(rc.Data, data); err != nil {
			return err
		}

		if err := dump(rc, filepath.Dir(rp), cacheDir, outputPath, nil); err != nil {
			return fmt.Errorf("recipe %q: %v", rp, err)
		}

	case ti.ComponentPath != "":
		// Fetch the component, which could be remote.
		cp, err := fileutil.Fetch(ti.ComponentPath, pwd, cacheDir)
		if err != nil {
			return err
		}

		write := template.WriteDir

		// If the component path is a single file,
		// treat the output_path as a file name and only write that out.
		// Otherwise, treat as directory path
		info, err := os.Stat(cp)
		if err != nil {
			return fmt.Errorf("stat %q: %v", cp, err)
		}
		if info.Mode().IsRegular() {
			write = template.WriteFile
		}

		if err := write(cp, outputPath, data); err != nil {
			return fmt.Errorf("component %q: %v", cp, err)
		}
	}
	return nil
}