// iterate performs a single iteration of all the templates, executing each template in order func (l *OptionsLoader) iterate(userConfig interface{}, current interface{}) (interface{}, error) { sort.Sort(l.templates) t := reflect.TypeOf(current).Elem() next := reflect.New(t).Interface() // Copy the current state before applying rules; they act as defaults utils.JsonMergeStruct(next, current) for _, t := range l.templates { glog.V(2).Infof("executing template %s (tags=%s)", t.Name, t.Tags) var buffer bytes.Buffer err := t.Template.ExecuteTemplate(&buffer, t.Name, current) if err != nil { return nil, fmt.Errorf("error executing template %q: %v", t.Name, err) } yamlBytes := buffer.Bytes() jsonBytes, err := utils.YamlToJson(yamlBytes) if err != nil { // TODO: It would be nice if yaml returned us the line number here glog.Infof("error parsing yaml. yaml follows:") for i, line := range strings.Split(string(yamlBytes), "\n") { fmt.Fprintf(os.Stderr, "%3d: %s\n", i, line) } return nil, fmt.Errorf("error parsing yaml %q: %v", t.Name, err) } err = json.Unmarshal(jsonBytes, next) if err != nil { return nil, fmt.Errorf("error parsing yaml (converted to JSON) %q: %v", t.Name, err) } } // Also copy the user-provided values after applying rules; they act as overrides now utils.JsonMergeStruct(next, userConfig) return next, nil }
func (l *Loader) BuildCompleteSpec(clusterSpec *api.ClusterSpec, modelStore string, models []string) (*api.ClusterSpec, error) { // First pass: load options tw := &loader.TreeWalker{ DefaultHandler: ignoreHandler, Contexts: map[string]loader.Handler{ "resources": ignoreHandler, }, Extensions: map[string]loader.Handler{ ".options": l.OptionsLoader.HandleOptions, }, Tags: l.Tags, } for _, model := range models { modelDir := path.Join(modelStore, model) err := tw.Walk(modelDir) if err != nil { return nil, err } } loaded, err := l.OptionsLoader.Build(clusterSpec) if err != nil { return nil, err } completed := &api.ClusterSpec{} *completed = *(loaded.(*api.ClusterSpec)) // Master kubelet config = (base kubelet config + master kubelet config) masterKubelet := &api.KubeletConfig{} utils.JsonMergeStruct(masterKubelet, completed.Kubelet) utils.JsonMergeStruct(masterKubelet, completed.MasterKubelet) completed.MasterKubelet = masterKubelet glog.V(1).Infof("options: %s", fi.DebugAsJsonStringIndent(completed)) return completed, nil }