diff --git a/server/handlers.go b/server/handlers.go index c3983ed3..202f5980 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -4,12 +4,12 @@ import ( "encoding/json" "fmt" "net/http" - - log "github.com/Sirupsen/logrus" - "github.com/gorilla/mux" - + "os" + "path/filepath" "time" + "github.com/Sirupsen/logrus" + "github.com/gorilla/mux" "github.com/jessfraz/reg/clair" "github.com/jessfraz/reg/registry" ) @@ -40,25 +40,17 @@ type AnalysisResult struct { Name string `json:"name"` } -func (rc *registryController) repositoriesHandler(w http.ResponseWriter, r *http.Request) { - log.WithFields(log.Fields{ - "func": "repositories", - "URL": r.URL, - "method": r.Method, - }).Info("fetching repositories") +func (rc *registryController) repositories(staticDir string) error { + updating = true + logrus.Info("fetching catalog") - result := AnalysisResult{} - result.RegistryDomain = rc.reg.Domain + result := AnalysisResult{ + RegistryDomain: rc.reg.Domain, + } - repoList, err := rc.reg.Catalog("") + repoList, err := r.Catalog("") if err != nil { - log.WithFields(log.Fields{ - "func": "repositories", - "URL": r.URL, - "method": r.Method, - }).Errorf("getting catalog failed: %v", err) - w.WriteHeader(http.StatusInternalServerError) - return + return fmt.Errorf("getting catalog failed: %v", err) } for _, repo := range repoList { @@ -71,19 +63,31 @@ func (rc *registryController) repositoriesHandler(w http.ResponseWriter, r *http result.Repositories = append(result.Repositories, r) } - if err := tmpl.ExecuteTemplate(w, "repositories", result); err != nil { - log.WithFields(log.Fields{ - "func": "repositories", - "URL": r.URL, - "method": r.Method, - }).Errorf("template rendering failed: %v", err) - w.WriteHeader(http.StatusInternalServerError) - return + // parse & execute the template + logrus.Info("executing the template repositories") + + path := filepath.Join(staticDir, "index.html") + if err := os.MkdirAll(filepath.Dir(path), 0644); err != nil { + return err } + logrus.Debugf("creating/opening file %s", path) + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + + if err := tmpl.ExecuteTemplate(f, "repositories", result); err != nil { + f.Close() + return fmt.Errorf("execute template repositories failed: %v", err) + } + + updating = false + return nil } func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request) { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "tags", "URL": r.URL, "method": r.Method, @@ -99,7 +103,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request tags, err := rc.reg.Tags(repo) if err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "tags", "URL": r.URL, "method": r.Method, @@ -117,7 +121,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request // get the manifest m1, err := rc.reg.ManifestV1(repo, tag) if err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "tags", "URL": r.URL, "method": r.Method, @@ -132,7 +136,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request var comp v1Compatibility if err := json.Unmarshal([]byte(h.V1Compatibility), &comp); err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "tags", "URL": r.URL, "method": r.Method, @@ -159,7 +163,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request if rc.cl != nil { vuln, err := rc.cl.Vulnerabilities(rc.reg, repo, tag, m1) if err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "tags", "URL": r.URL, "method": r.Method, @@ -174,7 +178,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request } if err := tmpl.ExecuteTemplate(w, "tags", result); err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "tags", "URL": r.URL, "method": r.Method, @@ -186,7 +190,7 @@ func (rc *registryController) tagsHandler(w http.ResponseWriter, r *http.Request } func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *http.Request) { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "vulnerabilities", "URL": r.URL, "method": r.Method, @@ -210,7 +214,7 @@ func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *h m1, err := rc.reg.ManifestV1(repo, tag) if err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "vulnerabilities", "URL": r.URL, "method": r.Method, @@ -224,7 +228,7 @@ func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *h var comp v1Compatibility if err := json.Unmarshal([]byte(h.V1Compatibility), &comp); err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "vulnerabilities", "URL": r.URL, "method": r.Method, @@ -241,7 +245,7 @@ func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *h if rc.cl != nil { result, err = rc.cl.Vulnerabilities(rc.reg, repo, tag, m1) if err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "vulnerabilities", "URL": r.URL, "method": r.Method, @@ -254,7 +258,7 @@ func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *h if r.Header.Get("Accept-Encoding") == "application/json" { js, err := json.Marshal(result) if err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "vulnerabilities", "URL": r.URL, "method": r.Method, @@ -269,7 +273,7 @@ func (rc *registryController) vulnerabilitiesHandler(w http.ResponseWriter, r *h } if err := tmpl.ExecuteTemplate(w, "vulns", result); err != nil { - log.WithFields(log.Fields{ + logrus.WithFields(logrus.Fields{ "func": "vulnerabilities", "URL": r.URL, "method": r.Method, diff --git a/server/server.go b/server/server.go index 46c7c2c9..53e544f1 100644 --- a/server/server.go +++ b/server/server.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/Sirupsen/logrus" "github.com/gorilla/mux" @@ -24,9 +25,10 @@ const ( ) var ( - r *registry.Registry - cl *clair.Clair - tmpl *template.Template + updating = false + r *registry.Registry + cl *clair.Clair + tmpl *template.Template ) // preload initializes any global options and configuration @@ -81,6 +83,11 @@ func main() { Name: "key", Usage: "path to ssl key", }, + cli.StringFlag{ + Name: "interval", + Value: "5m", + Usage: "interval to generate new index.html's at", + }, cli.StringFlag{ Name: "clair", Usage: "url to clair instance", @@ -170,17 +177,46 @@ func main() { cl: cl, } + // create the initial index + logrus.Info("creating initial static index") + if err := rc.repositories(staticDir); err != nil { + logrus.Fatalf("Error creating index: %v", err) + } + + // parse the duration + dur, err := time.ParseDuration(c.String("interval")) + if err != nil { + logrus.Fatalf("parsing %s as duration failed: %v", c.String("interval"), err) + } + ticker := time.NewTicker(dur) + + go func() { + // create more indexes every X minutes based off interval + for range ticker.C { + if !updating { + logrus.Info("creating timer based static index") + if err := rc.repositories(staticDir); err != nil { + logrus.Warnf("creating static index failed: %v", err) + updating = false + } + } else { + logrus.Warnf("skipping timer based static index update for %s", c.String("interval")) + } + } + }() + // create mux server mux := mux.NewRouter() // static files handler staticHandler := http.FileServer(http.Dir(staticDir)) - mux.Handle("/static/", http.StripPrefix("/static/", staticHandler)) + mux.Handle("/", staticHandler) mux.HandleFunc("/repo/{repo}", rc.tagsHandler) + mux.HandleFunc("/repo/{repo}/", rc.tagsHandler) mux.HandleFunc("/repo/{repo}/{tag}", rc.vulnerabilitiesHandler) mux.HandleFunc("/repo/{repo}/{tag}/", rc.vulnerabilitiesHandler) mux.HandleFunc("/repo/{repo}/{tag}/vulns", rc.vulnerabilitiesHandler) - mux.HandleFunc("/", rc.repositoriesHandler) + mux.HandleFunc("/repo/{repo}/{tag}/vulns/", rc.vulnerabilitiesHandler) // set up the server port := c.String("port") diff --git a/server/templates/repositories.html b/server/templates/repositories.html index e9fa4684..b4e39f1a 100644 --- a/server/templates/repositories.html +++ b/server/templates/repositories.html @@ -9,8 +9,8 @@ {{ .RegistryDomain }} - - + +

{{ .RegistryDomain }}

@@ -45,7 +45,7 @@ - +