func loadTemplate(args []string) *common.Template { var template *common.Template var err error if len(args) < 2 { fmt.Fprintln(os.Stderr, "No template name or configuration(s) supplied") usage() } if len(args) < 3 { if t := getRegistryType(args[1]); t != nil { template = buildTemplateFromType(*t) } else { template, err = expander.NewTemplateFromRootTemplate(args[1]) } } else { template, err = expander.NewTemplateFromFileNames(args[1], args[2:]) } if err != nil { log.Fatalf("cannot create configuration from supplied arguments: %s\n", err) } // Override name if set from flags. if *deployment_name != "" { template.Name = *deployment_name } return template }
// ExpandTemplate expands the supplied template, and returns a configuration. // It will also update the imports in the provided template if any were added // during type resolution. func (e *expander) ExpandTemplate(t *common.Template) (*ExpandedTemplate, error) { // We have a fencepost problem here. // 1. Start by trying to resolve any missing templates // 2. Expand the configuration using all the of the imports available to us at this point // 3. Expansion may yield additional templates, so we run the type resolution again // 4. If type resolution resulted in new imports being available, return to 2. config := &common.Configuration{} if err := yaml.Unmarshal([]byte(t.Content), config); err != nil { e := fmt.Errorf("Unable to unmarshal configuration (%s): %s", err, t.Content) return nil, e } var finalLayout *common.Layout needResolve := map[string]*common.LayoutResource{} // Start things off by attempting to resolve the templates in a first pass. newImp, err := e.typeResolver.ResolveTypes(config, t.Imports) if err != nil { e := fmt.Errorf("type resolution failed: %s", err) return nil, expanderError(t, e) } t.Imports = append(t.Imports, newImp...) for { // Now expand with everything imported. result, err := e.expandTemplate(t) if err != nil { e := fmt.Errorf("template expansion: %s", err) return nil, expanderError(t, e) } // Once we set this layout, we're operating on the "needResolve" *LayoutResources, // which are pointers into the original layout structure. After each expansion we // lose the templates in the previous expansion, so we have to keep the first one // around and keep appending to the pointers in it as we get more layers of expansion. if finalLayout == nil { finalLayout = result.Layout } needResolve = walkLayout(result.Layout, t.Imports, needResolve) newImp, err = e.typeResolver.ResolveTypes(result.Config, t.Imports) if err != nil { e := fmt.Errorf("type resolution failed: %s", err) return nil, expanderError(t, e) } // If the new imports contain nothing, we are done. Everything is fully expanded. if len(newImp) == 0 { result.Layout = finalLayout return result, nil } // Update imports with any new imports from type resolution. t.Imports = append(t.Imports, newImp...) } }
func loadTemplate(args []string) *common.Template { var template *common.Template var err error if len(args) < 2 { fmt.Fprintln(os.Stderr, "No template name or configuration(s) supplied") usage() } if *stdin { if len(args) < 2 { usage() } input, err := ioutil.ReadAll(os.Stdin) if err != nil { panic(err) } r := bytes.NewReader(input) template, err = expander.NewTemplateFromArchive(args[1], r, args[2:]) if err != nil { if err != tar.ErrHeader { panic(err) } r := bytes.NewReader(input) template, err = expander.NewTemplateFromReader(args[1], r, args[2:]) if err != nil { panic(fmt.Errorf("cannot create configuration from supplied arguments: %s\n", err)) } } } else { // See if the first argument is a local file. It could either be a type, or it could be a configuration. If // it's a local file, it's configuration. if _, err := os.Stat(args[1]); err == nil { if len(args) > 2 { template, err = expander.NewTemplateFromFileNames(args[1], args[2:]) } else { template, err = expander.NewTemplateFromRootTemplate(args[1]) } } else { template = buildTemplateFromType(args[1]) } if err != nil { panic(fmt.Errorf("cannot create configuration from supplied arguments: %s\n", err)) } } // Override name if set from flags. if *deployment_name != "" { template.Name = *deployment_name } return template }
func loadTemplate(args []string) *common.Template { var template *common.Template var err error if len(args) < 2 { fmt.Fprintln(os.Stderr, "No template name or configuration(s) supplied") usage() } if *stdin { if len(args) < 2 { usage() } input, err := ioutil.ReadAll(os.Stdin) if err != nil { panic(err) } r := bytes.NewReader(input) template, err = expander.NewTemplateFromArchive(args[1], r, args[2:]) if err != nil { if err != tar.ErrHeader { panic(err) } r := bytes.NewReader(input) template, err = expander.NewTemplateFromReader(args[1], r, args[2:]) if err != nil { panic(fmt.Errorf("cannot create configuration from supplied arguments: %s\n", err)) } } } else { if len(args) < 3 { if t := getRegistryType(args[1]); t != nil { template = buildTemplateFromType(*t) } else { template, err = expander.NewTemplateFromRootTemplate(args[1]) } } else { template, err = expander.NewTemplateFromFileNames(args[1], args[2:]) } if err != nil { panic(fmt.Errorf("cannot create configuration from supplied arguments: %s\n", err)) } } // Override name if set from flags. if *deployment_name != "" { template.Name = *deployment_name } return template }