mirror of
https://github.com/genuinetools/reg.git
synced 2024-09-28 11:46:20 -04:00
index with interval
Signed-off-by: Jess Frazelle <acidburn@google.com>
This commit is contained in:
parent
183c0d5ba3
commit
abc0d51801
5 changed files with 92 additions and 52 deletions
|
@ -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,
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
<base href="/" >
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>{{ .RegistryDomain }}</title>
|
||||
<link rel="icon" type="image/ico" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/styles.css" />
|
||||
<link rel="icon" type="image/ico" href="/favicon.ico">
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ .RegistryDomain }}</h1>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<div class="footer">
|
||||
<a href="https://twitter.com/jessfraz">@jessfraz</a>
|
||||
</div><!--/.footer-->
|
||||
<script src="/static/js/scripts.js"></script>
|
||||
<script src="/js/scripts.js"></script>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
<base href="/" >
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>{{ .RegistryDomain }}/{{ .Name }}</title>
|
||||
<link rel="icon" type="image/ico" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/styles.css" />
|
||||
<link rel="icon" type="image/ico" href="/favicon.ico">
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ .RegistryDomain }}/{{ .Name }}</h1>
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
<base href="/" >
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>{{ .RegistryURL }}/{{ .Repo }}:{{ .Tag }} Vulnerability Report</title>
|
||||
<link rel="icon" type="image/ico" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
|
||||
<link rel="icon" type="image/ico" href="/favicon.ico">
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
|
Loading…
Reference in a new issue