From d0c3ab9dfe3fdae3853704003582a006cbf7f6df Mon Sep 17 00:00:00 2001 From: Jess Frazelle Date: Mon, 16 Jul 2018 04:52:57 -0400 Subject: [PATCH] generate tags Signed-off-by: Jess Frazelle --- .gitignore | 2 ++ handlers.go | 75 ++++++++++++++++++++++++++++++----------------------- server.go | 8 +++--- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index a148e10b..7b57c209 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,8 @@ testreg .certs cross/ internal/ +server/static/index.html +server/static/repo/ # Go coverage results coverage.txt diff --git a/handlers.go b/handlers.go index 3a27acdf..1b529a08 100644 --- a/handlers.go +++ b/handlers.go @@ -1,9 +1,11 @@ package main import ( + "bytes" "encoding/json" "fmt" "html/template" + "io/ioutil" "net/http" "net/url" "os" @@ -47,7 +49,7 @@ type AnalysisResult struct { LastUpdated string `json:"lastUpdated"` } -func (rc *registryController) repositories(staticDir string) error { +func (rc *registryController) repositories(staticDir string, generateTagsFiles bool) error { rc.l.Lock() defer rc.l.Unlock() @@ -71,6 +73,23 @@ func (rc *registryController) repositories(staticDir string) error { } result.Repositories = append(result.Repositories, r) + + if generateTagsFiles { + // Parse and execute the tags templates. + logrus.Infof("generating static tags page for repo %s", repo) + b, err := rc.generateTagsTemplate(repo) + if err != nil { + logrus.Warnf("generating tags tamplate for repo %q failed: %v", repo, err) + } + tagsDir := filepath.Join(staticDir, "repo", repo, "tags") + if err := os.MkdirAll(tagsDir, 0644); err != nil { + return err + } + tagsFile := filepath.Join(tagsDir, "index.html") + if err := ioutil.WriteFile(tagsFile, b, 0644); err != nil { + logrus.Warnf("writing tags tamplate for repo %s to %sfailed: %v", repo, tagsFile, err) + } + } } // Parse & execute the template. @@ -110,7 +129,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request return } - tags, err := rc.reg.Tags(repo) + b, err := rc.generateTagsTemplate(repo) if err != nil { logrus.WithFields(logrus.Fields{ "func": "tags", @@ -118,16 +137,24 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request "method": r.Method, }).Errorf("getting tags for %s failed: %v", repo, err) - w.WriteHeader(http.StatusNotFound) - fmt.Fprint(w, "No tags found") + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Getting tags for %s failed", repo) return } - // Error out if there are no tags / images (the above err != nil does not error out when nothing has been found) + fmt.Fprint(w, b) +} + +func (rc *registryController) generateTagsTemplate(repo string) ([]byte, error) { + tags, err := rc.reg.Tags(repo) + if err != nil { + return nil, fmt.Errorf("getting tags for %s failed: %v", repo, err) + } + + // Error out if there are no tags / images + // (the above err != nil does not error out when nothing has been found) if len(tags) == 0 { - w.WriteHeader(http.StatusNotFound) - fmt.Fprint(w, "No tags found") - return + return nil, fmt.Errorf("No tags found for repo: %s", repo) } result := AnalysisResult{ @@ -140,16 +167,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request // get the manifest m1, err := rc.reg.ManifestV1(repo, tag) if err != nil { - logrus.WithFields(logrus.Fields{ - "func": "tags", - "URL": r.URL, - "method": r.Method, - "repo": repo, - "tag": tag, - }).Errorf("getting v1 manifest for %s:%s failed: %v", repo, tag, err) - w.WriteHeader(http.StatusNotFound) - fmt.Fprint(w, "Manifest not found") - return + return nil, fmt.Errorf("getting v1 manifest for %s:%s failed: %v", repo, tag, err) } var createdDate time.Time @@ -157,13 +175,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request var comp v1Compatibility if err := json.Unmarshal([]byte(h.V1Compatibility), &comp); err != nil { - logrus.WithFields(logrus.Fields{ - "func": "tags", - "URL": r.URL, - "method": r.Method, - }).Errorf("unmarshal v1 manifest for %s:%s failed: %v", repo, tag, err) - w.WriteHeader(http.StatusInternalServerError) - return + return nil, fmt.Errorf("unmarshal v1 manifest for %s:%s failed: %v", repo, tag, err) } createdDate = comp.Created @@ -184,15 +196,12 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request result.Repositories = append(result.Repositories, rp) } - if err := rc.tmpl.ExecuteTemplate(w, "tags", result); err != nil { - logrus.WithFields(logrus.Fields{ - "func": "tags", - "URL": r.URL, - "method": r.Method, - }).Errorf("template rendering failed: %v", err) - w.WriteHeader(http.StatusInternalServerError) - return + var buf bytes.Buffer + if err := rc.tmpl.ExecuteTemplate(&buf, "tags", result); err != nil { + return nil, fmt.Errorf("template rendering failed: %v", err) } + + return buf.Bytes(), nil } func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *http.Request) { diff --git a/server.go b/server.go index 5620ecda..45a2a69b 100644 --- a/server.go +++ b/server.go @@ -127,7 +127,7 @@ func (cmd *serverCommand) Run(ctx context.Context, args []string) error { // Create the initial index. logrus.Info("creating initial static index") - if err := rc.repositories(staticDir); err != nil { + if err := rc.repositories(staticDir, true); err != nil { return fmt.Errorf("creating index failed: %v", err) } @@ -141,7 +141,7 @@ func (cmd *serverCommand) Run(ctx context.Context, args []string) error { // Create more indexes every X minutes based off interval. for range ticker.C { logrus.Info("creating timer based static index") - if err := rc.repositories(staticDir); err != nil { + if err := rc.repositories(staticDir, false); err != nil { logrus.Warnf("creating static index failed: %v", err) } } @@ -152,7 +152,6 @@ func (cmd *serverCommand) Run(ctx context.Context, args []string) error { mux.UseEncodedPath() // Static files handler. - staticHandler := http.FileServer(http.Dir(staticDir)) mux.HandleFunc("/repo/{repo}/tags", rc.tagsHandler) mux.HandleFunc("/repo/{repo}/tags/", rc.tagsHandler) mux.HandleFunc("/repo/{repo}/tag/{tag}", rc.vulnerabilitiesHandler) @@ -160,6 +159,9 @@ func (cmd *serverCommand) Run(ctx context.Context, args []string) error { mux.HandleFunc("/repo/{repo}/tag/{tag}/vulns", rc.vulnerabilitiesHandler) mux.HandleFunc("/repo/{repo}/tag/{tag}/vulns/", rc.vulnerabilitiesHandler) mux.HandleFunc("/repo/{repo}/tag/{tag}/vulns.json", rc.vulnerabilitiesHandler) + + // Serve the static assets. + staticHandler := http.FileServer(http.Dir(staticDir)) mux.PathPrefix("/static/").Handler(http.StripPrefix("/static/", staticHandler)) mux.Handle("/", staticHandler)