// MapFetchableUrl checks a type to see if it is either a short git hub url or a fully specified URL // and returns the URL that should be used to fetch it. If the url is not fetchable (primitive type for // example) will return empty string. func (tr *typeResolver) MapFetchableURL(t string) (string, error) { if util.IsGithubShortType(t) { return tr.ShortTypeToDownloadURL(t) } else if util.IsHttpUrl(t) { return t, nil } return "", nil }
// MapFetchableUrls checks a type to see if it is either a short git hub url or a fully specified URL // and returns the URL that should be used to fetch it. If the url is not fetchable (primitive type for // example) will return empty string. func (tr *typeResolver) MapFetchableURLs(t string) ([]string, error) { if util.IsGithubShortType(t) { return tr.ShortTypeToDownloadURLs(t) } else if util.IsGithubShortPackageType(t) { return tr.ShortTypeToPackageDownloadURLs(t) } else if util.IsHttpUrl(t) { return []string{t}, nil } return []string{}, nil }
func getTypeUrl(tName string) string { if util.IsHttpUrl(tName) { // User can pass raw URL to template. return tName } // User can pass registry type. t := getRegistryType(tName) if t == nil { log.Fatalf("Invalid type name, must be in the form \"<type-name>:<version>\": %s", tName) } return getDownloadUrl(*t) }
// getTypeURLs returns URLs or empty list if a primitive type. func getTypeURLs(tName string) []string { if util.IsHttpUrl(tName) { // User can pass raw URL to template. return []string{tName} } // User can pass registry type. t := getRegistryType(tName) if t == nil { // Primitive types have no associated URL. return []string{} } return getDownloadURLs(*t) }
// GetDownloadURLs checks a type to see if it is either a short git hub url or a fully specified URL // and returns the URLs that should be used to fetch it. If the url is not fetchable (primitive type // for example), it returns an empty slice. func GetDownloadURLs(rp RegistryProvider, t string) ([]string, error) { if IsGithubShortType(t) { return ShortTypeToDownloadURLs(rp, t) } else if IsGithubShortPackageType(t) { return ShortTypeToPackageDownloadURLs(rp, t) } else if util.IsHttpUrl(t) { result, err := url.Parse(t) if err != nil { return nil, fmt.Errorf("cannot parse download URL %s: %s", t, err) } return []string{result.String()}, nil } return []string{}, nil }
// ResolveTypes resolves the types in the supplied configuration and returns // resolved type definitions in t.ImportFiles. Types can be either // primitive (i.e., built in), resolved (i.e., already t.ImportFiles), or remote // (i.e., described by a URL that must be fetched to resolve the type). func (tr *typeResolver) ResolveTypes(config *Configuration, imports []*ImportFile) ([]*ImportFile, error) { existing := map[string]bool{} for _, v := range imports { existing[v.Name] = true } fetched := map[string][]*ImportFile{} toFetch := make([]string, 0, tr.maxUrls) for _, r := range config.Resources { // Only fetch HTTP URLs that we haven't already imported. if util.IsHttpUrl(r.Type) && !existing[r.Type] { toFetch = append(toFetch, r.Type) fetched[r.Type] = append(fetched[r.Type], &ImportFile{Name: r.Type}) } } count := 0 for len(toFetch) > 0 { //1. Fetch import URL. Exit if no URLs left //2. Check/handle HTTP status //3. Store results in all ImportFiles from that URL //4. Check for the optional schema file at import URL + .schema //5. Repeat 2,3 for schema file //6. Add each schema import to fetch if not already done //7. Mark URL done. Return to 1. if count >= tr.maxUrls { return nil, resolverError(config, fmt.Errorf("Number of imports exceeds maximum of %d", tr.maxUrls)) } url := toFetch[0] template, err := performHTTPGet(tr.getter, url, false) if err != nil { return nil, resolverError(config, err) } for _, i := range fetched[url] { i.Content = template } schemaURL := url + schemaSuffix sch, err := performHTTPGet(tr.getter, schemaURL, true) if err != nil { return nil, resolverError(config, err) } if sch != "" { var s Schema if err := yaml.Unmarshal([]byte(sch), &s); err != nil { return nil, resolverError(config, err) } // Here we handle any nested imports in the schema we've just fetched. for _, v := range s.Imports { i := &ImportFile{Name: v.Name} var existingSchema string if len(fetched[v.Path]) == 0 { // If this import URL is new to us, add it to the URLs to fetch. toFetch = append(toFetch, v.Path) } else { // If this is not a new import URL and we've already fetched its contents, // reuse them. Also, check if we also found a schema for that import URL and // record those contents for re-use as well. if fetched[v.Path][0].Content != "" { i.Content = fetched[v.Path][0].Content if len(fetched[v.Path+schemaSuffix]) > 0 { existingSchema = fetched[v.Path+schemaSuffix][0].Content } } } fetched[v.Path] = append(fetched[v.Path], i) if existingSchema != "" { fetched[v.Path+schemaSuffix] = append(fetched[v.Path+schemaSuffix], &ImportFile{Name: v.Name + schemaSuffix, Content: existingSchema}) } } // Add the schema we've fetched as the schema for any templates which used this URL. for _, i := range fetched[url] { schemaImportName := i.Name + schemaSuffix fetched[schemaURL] = append(fetched[schemaURL], &ImportFile{Name: schemaImportName, Content: sch}) } } count = count + 1 toFetch = toFetch[1:] } ret := []*ImportFile{} for _, v := range fetched { ret = append(ret, v...) } return ret, nil }