diff --git a/README.md b/README.md index 3b1b661f8..16dc2a4cb 100644 --- a/README.md +++ b/README.md @@ -225,22 +225,24 @@ Run a static UI server for a registry. Flags: - -u, --username username for the registry (default: ) - --listen-address address to listen on (default: ) --asset-path Path to assets and templates (default: ) - -f, --force-non-ssl force allow use of non-ssl (default: false) - --once generate the templates once and then exit (default: false) - --skip-ping skip pinging the registry while establishing connection (default: false) - --timeout timeout for HTTP requests (default: 1m0s) + --auth-url alternate URL for registry authentication (ex. auth.docker.io) (default: ) --cert path to ssl cert (default: ) + --clair url to clair instance (default: ) -d enable debug logging (default: false) + -f, --force-non-ssl force allow use of non-ssl (default: false) + --interval interval to generate new index.html's at (default: 1h0m0s) + -k, --insecure do not verify tls certificates (default: false) --key path to ssl key (default: ) + --listen-address address to listen on (default: ) + --once generate the templates once and then exit (default: false) + -p, --password password for the registry (default: ) --port port for server to run on (default: 8080) -r, --registry URL to the private registry (ex. r.j3ss.co) (default: ) - --clair url to clair instance (default: ) - -k, --insecure do not verify tls certificates (default: false) - --interval interval to generate new index.html's at (default: 1h0m0s) - -p, --password password for the registry (default: ) + --skip-ping skip pinging the registry while establishing connection (default: false) + --sort generate tag templates sorted by property (one of: created) (default: created) + --timeout timeout for HTTP requests (default: 1m0s) + -u, --username username for the registry (default: ) ``` **Screenshots:** @@ -283,4 +285,4 @@ against an insecure registry. **OR** Run `make dind dtest` to avoid having to change your local docker config and -to run the tests as docker-in-docker. \ No newline at end of file +to run the tests as docker-in-docker. diff --git a/handlers.go b/handlers.go index 362041685..594fea169 100644 --- a/handlers.go +++ b/handlers.go @@ -11,6 +11,7 @@ import ( "net/url" "os" "path/filepath" + "sort" "strings" "sync" "time" @@ -28,6 +29,7 @@ type registryController struct { l sync.Mutex tmpl *template.Template generateOnly bool + repoSortBy string } type v1Compatibility struct { @@ -44,6 +46,16 @@ type Repository struct { VulnerabilityReport clair.VulnerabilityReport `json:"vulnerability"` } +const ( + sortByCreated = "created" +) + +type repoByDate []Repository + +func (r repoByDate) Len() int { return len(r) } +func (r repoByDate) Less(i, j int) bool { return r[i].Created.Before(r[j].Created) } +func (r repoByDate) Swap(i, j int) { r[i], r[j] = r[j], r[i] } + // An AnalysisResult holds all vulnerabilities of a scan type AnalysisResult struct { Repositories []Repository `json:"repositories"` @@ -228,6 +240,11 @@ func (rc *registryController) generateTagsTemplate(ctx context.Context, repo str result.Repositories = append(result.Repositories, rp) } + switch rc.repoSortBy { + case sortByCreated: + sort.Sort(sort.Reverse(repoByDate(result.Repositories))) + } + // Execute the template. var buf bytes.Buffer if err := rc.tmpl.ExecuteTemplate(&buf, "tags", result); err != nil { diff --git a/server.go b/server.go index fcd4cd71e..b6ae6752e 100644 --- a/server.go +++ b/server.go @@ -43,6 +43,10 @@ func (cmd *serverCommand) Register(fs *flag.FlagSet) { fs.StringVar(&cmd.assetPath, "asset-path", "", "Path to assets and templates") fs.BoolVar(&cmd.generateAndExit, "once", false, "generate the templates once and then exit") + + sortOpts := []string{sortByCreated} + fs.StringVar(&cmd.repoSortBy, "sort", sortByCreated, + fmt.Sprintf("generate tag templates sorted by property (one of: %s)", strings.Join(sortOpts, ","))) } type serverCommand struct { @@ -57,6 +61,7 @@ type serverCommand struct { listenAddress string port string assetPath string + repoSortBy string } func (cmd *serverCommand) Run(ctx context.Context, args []string) error { @@ -66,10 +71,15 @@ func (cmd *serverCommand) Run(ctx context.Context, args []string) error { return err } + if cmd.repoSortBy != sortByCreated { + return fmt.Errorf("sort option invalid; '%s' is not valid", cmd.repoSortBy) + } + // Create the registry controller for the handlers. rc := registryController{ reg: r, generateOnly: cmd.generateAndExit, + repoSortBy: cmd.repoSortBy, } // Create a clair client if the user passed in a server address.