diff --git a/dm/dm.go b/dm/dm.go index ee7c2954b..bbe343221 100644 --- a/dm/dm.go +++ b/dm/dm.go @@ -168,7 +168,13 @@ func execute() { path := fmt.Sprintf("registries/%s/types", *templateRegistry) callService(path, "GET", "list templates", nil) case "describe": - describeType(args) + if len(args) != 2 { + fmt.Fprintln(os.Stderr, "No type name or URL supplied") + os.Exit(1) + } + + path := fmt.Sprintf("types/%s/metadata", url.QueryEscape(args[1])) + callService(path, "GET", "get metadata for type", nil) case "expand": template := loadTemplate(args) callService("expand", "POST", "expand configuration", marshalTemplate(template)) @@ -308,42 +314,6 @@ func callHTTP(path, method, action string, reader io.ReadCloser) string { return string(body) } -// describeType prints the schema for a type specified by either a -// template URL or a fully qualified registry type name (e.g., -// :) -func describeType(args []string) { - if len(args) != 2 { - fmt.Fprintln(os.Stderr, "No type name or URL supplied") - os.Exit(1) - } - - tUrls := getDownloadURLs(url.QueryEscape(args[1])) - if len(tUrls) == 0 { - panic(fmt.Errorf("Invalid type name, must be a template URL or in the form \":\": %s", args[1])) - } - - if !strings.Contains(tUrls[0], ".prov") { - // It's not a chart, so grab the schema - path := fmt.Sprintf("registries/%s/download?file=%s.schema", *templateRegistry, url.QueryEscape(tUrls[0])) - callService(path, "GET", "get schema for type ("+tUrls[0]+")", nil) - } else { - // It's a chart, so grab the provenance file - path := fmt.Sprintf("registries/%s/download?file=%s", *templateRegistry, url.QueryEscape(tUrls[0])) - callService(path, "GET", "get file", nil) - } -} - -// getDownloadURLs returns URLs for a type in the given registry -func getDownloadURLs(tName string) []string { - path := fmt.Sprintf("%s/registries/%s/types/%s", *service, *templateRegistry, url.QueryEscape(tName)) - resp := callHTTP(path, "GET", "get download urls", nil) - u := []string{} - if err := json.Unmarshal([]byte(resp), &u); err != nil { - panic(fmt.Errorf("Failed to parse JSON response from service: %s", resp)) - } - return u -} - func loadTemplate(args []string) *common.Template { var template *common.Template var err error diff --git a/expandybird/expander/expander.go b/expandybird/expander/expander.go index 86ad3bf6b..0dfb6ac7d 100644 --- a/expandybird/expander/expander.go +++ b/expandybird/expander/expander.go @@ -46,6 +46,8 @@ func NewExpander(binary string) Expander { return &expander{binary} } +// NewTemplateFromType creates and returns a new template whose content +// is a YAML marshaled resource assembled from the supplied arguments. func NewTemplateFromType(name, typeName string, properties map[string]interface{}) (*common.Template, error) { resource := &common.Resource{ Name: name, diff --git a/manager/deployments.go b/manager/deployments.go index 8134c8e63..421693af9 100644 --- a/manager/deployments.go +++ b/manager/deployments.go @@ -53,6 +53,8 @@ var deployments = []Route{ {"Expand", "/expand", "POST", expandHandlerFunc, ""}, {"ListTypes", "/types", "GET", listTypesHandlerFunc, ""}, {"ListTypeInstances", "/types/{type}/instances", "GET", listTypeInstancesHandlerFunc, ""}, + {"GetRegistryForType", "/types/{type}/registry", "GET", getRegistryForTypeHandlerFunc, ""}, + {"GetMetadataForType", "/types/{type}/metadata", "GET", getMetadataForTypeHandlerFunc, ""}, {"ListRegistries", "/registries", "GET", listRegistriesHandlerFunc, ""}, {"GetRegistry", "/registries/{registry}", "GET", getRegistryHandlerFunc, ""}, {"CreateRegistry", "/registries/{registry}", "POST", createRegistryHandlerFunc, "JSON"}, @@ -378,6 +380,40 @@ func listTypeInstancesHandlerFunc(w http.ResponseWriter, r *http.Request) { util.LogHandlerExitWithJSON(handler, w, instances, http.StatusOK) } +func getRegistryForTypeHandlerFunc(w http.ResponseWriter, r *http.Request) { + handler := "manager: get type registry" + util.LogHandlerEntry(handler, r) + typeName, err := getPathVariable(w, r, "type", handler) + if err != nil { + return + } + + registry, err := backend.GetRegistryForType(typeName) + if err != nil { + util.LogAndReturnError(handler, http.StatusBadRequest, err, w) + return + } + + util.LogHandlerExitWithJSON(handler, w, registry, http.StatusOK) +} + +func getMetadataForTypeHandlerFunc(w http.ResponseWriter, r *http.Request) { + handler := "manager: get type metadata" + util.LogHandlerEntry(handler, r) + typeName, err := getPathVariable(w, r, "type", handler) + if err != nil { + return + } + + metadata, err := backend.GetMetadataForType(typeName) + if err != nil { + util.LogAndReturnError(handler, http.StatusBadRequest, err, w) + return + } + + util.LogHandlerExitWithJSON(handler, w, metadata, http.StatusOK) +} + // Putting Registry handlers here for now because deployments.go // currently owns its own Manager backend and doesn't like to share. func listRegistriesHandlerFunc(w http.ResponseWriter, r *http.Request) { diff --git a/manager/manager/manager.go b/manager/manager/manager.go index 1245445aa..801b09fab 100644 --- a/manager/manager/manager.go +++ b/manager/manager/manager.go @@ -21,6 +21,7 @@ import ( "log" "net/url" "regexp" + "strings" "time" "github.com/kubernetes/deployment-manager/common" @@ -46,6 +47,8 @@ type Manager interface { // Types ListTypes() ([]string, error) ListInstances(typeName string) ([]*common.TypeInstance, error) + GetRegistryForType(typeName string) (string, error) + GetMetadataForType(typeName string) (string, error) // Registries ListRegistries() ([]*common.Registry, error) @@ -334,6 +337,42 @@ func (m *manager) ListInstances(typeName string) ([]*common.TypeInstance, error) return m.repository.GetTypeInstances(typeName) } +// GetRegistryForType returns the registry where a type resides. +func (m *manager) GetRegistryForType(typeName string) (string, error) { + _, r, err := registry.GetDownloadURLs(m.registryProvider, typeName) + if err != nil { + return "", err + } + + return r.GetRegistryName(), nil +} + +// GetMetadataForType returns the metadata for type. +func (m *manager) GetMetadataForType(typeName string) (string, error) { + URLs, r, err := registry.GetDownloadURLs(m.registryProvider, typeName) + if err != nil { + return "", err + } + + if len(URLs) < 1 { + return "", nil + } + + // If it's a chart, we want the provenance file + fPath := URLs[0] + if !strings.Contains(fPath, ".prov") { + // It's not a chart, so we want the schema + fPath += ".schema" + } + + metadata, err := getFileFromRegistry(fPath, r) + if err != nil { + return "", fmt.Errorf("cannot get metadata for type (%s): %s", typeName, err) + } + + return metadata, nil +} + // ListRegistries returns the list of registries func (m *manager) ListRegistries() ([]*common.Registry, error) { return m.service.List() @@ -403,11 +442,16 @@ func (m *manager) GetFile(registryName string, url string) (string, error) { return "", err } + return getFileFromRegistry(url, r) +} + +func getFileFromRegistry(url string, r registry.Registry) (string, error) { getter := util.NewHTTPClient(3, r, util.NewSleeper()) body, _, err := getter.Get(url) if err != nil { return "", err } + return body, nil }