generate tags

Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
Jess Frazelle 2018-07-16 04:52:57 -04:00
parent bd1c391295
commit d0c3ab9dfe
No known key found for this signature in database
GPG key ID: 18F3685C0022BFF3
3 changed files with 49 additions and 36 deletions

2
.gitignore vendored
View file

@ -47,6 +47,8 @@ testreg
.certs
cross/
internal/
server/static/index.html
server/static/repo/
# Go coverage results
coverage.txt

View file

@ -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) {

View file

@ -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)