github.com/chenbh/concourse/v6@v6.4.2/fly/commands/internal/templatehelpers/yaml_template.go (about) 1 package templatehelpers 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 7 "github.com/chenbh/concourse/v6/atc" 8 "github.com/chenbh/concourse/v6/fly/commands/internal/flaghelpers" 9 "github.com/chenbh/concourse/v6/vars" 10 "sigs.k8s.io/yaml" 11 ) 12 13 type YamlTemplateWithParams struct { 14 filePath atc.PathFlag 15 templateVariablesFiles []atc.PathFlag 16 templateVariables []flaghelpers.VariablePairFlag 17 yamlTemplateVariables []flaghelpers.YAMLVariablePairFlag 18 } 19 20 func NewYamlTemplateWithParams(filePath atc.PathFlag, templateVariablesFiles []atc.PathFlag, templateVariables []flaghelpers.VariablePairFlag, yamlTemplateVariables []flaghelpers.YAMLVariablePairFlag) YamlTemplateWithParams { 21 return YamlTemplateWithParams{ 22 filePath: filePath, 23 templateVariablesFiles: templateVariablesFiles, 24 templateVariables: templateVariables, 25 yamlTemplateVariables: yamlTemplateVariables, 26 } 27 } 28 29 func (yamlTemplate YamlTemplateWithParams) Evaluate( 30 allowEmpty bool, 31 strict bool, 32 ) ([]byte, error) { 33 config, err := ioutil.ReadFile(string(yamlTemplate.filePath)) 34 if err != nil { 35 return nil, fmt.Errorf("could not read file: %s", err.Error()) 36 } 37 38 if strict { 39 // We use a generic map here, since templates are not evaluated yet. 40 // (else a template string may cause an error when a struct is expected) 41 // If we don't check Strict now, then the subsequent steps will mask any 42 // duplicate key errors. 43 // We should consider being strict throughout the entire stack by default. 44 err = yaml.UnmarshalStrict(config, make(map[string]interface{})) 45 if err != nil { 46 return nil, fmt.Errorf("error parsing yaml before applying templates: %s", err.Error()) 47 } 48 } 49 50 var params []vars.Variables 51 52 // first, we take explicitly specified variables on the command line 53 flagVars := vars.StaticVariables{} 54 for _, f := range yamlTemplate.templateVariables { 55 flagVars[f.Name] = f.Value 56 } 57 for _, f := range yamlTemplate.yamlTemplateVariables { 58 flagVars[f.Name] = f.Value 59 } 60 params = append(params, flagVars) 61 62 // second, we take all files. with values in the files specified later on command line taking precedence over the 63 // same values in the files specified earlier on command line 64 for i := len(yamlTemplate.templateVariablesFiles) - 1; i >= 0; i-- { 65 path := yamlTemplate.templateVariablesFiles[i] 66 templateVars, err := ioutil.ReadFile(string(path)) 67 if err != nil { 68 return nil, fmt.Errorf("could not read template variables file (%s): %s", string(path), err.Error()) 69 } 70 71 var staticVars vars.StaticVariables 72 err = yaml.Unmarshal(templateVars, &staticVars) 73 if err != nil { 74 return nil, fmt.Errorf("could not unmarshal template variables (%s): %s", string(path), err.Error()) 75 } 76 77 params = append(params, staticVars) 78 } 79 80 evaluatedConfig, err := vars.NewTemplateResolver(config, params).Resolve(false, allowEmpty) 81 if err != nil { 82 return nil, err 83 } 84 85 return evaluatedConfig, nil 86 }