Skip to content

Commit cfb87f8

Browse files
committed
server: add sort option
This adds a '--sort' to the 'server' sub-command. Currently there is only one sort option, which is by create date. I assumed that his is useful in general, compared to a random order, so I made this the default. This is slightly over engineered, but makes it easier to add additional sorting options later. One that comes to my mind is sorting by tag (some kind of natsort/semversort). Signed-off-by: Roland Kammerer <[email protected]>
1 parent e29a4fd commit cfb87f8

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

README.md

+13-11
Original file line numberDiff line numberDiff line change
@@ -225,22 +225,24 @@ Run a static UI server for a registry.
225225

226226
Flags:
227227

228-
-u, --username username for the registry (default: <none>)
229-
--listen-address address to listen on (default: <none>)
230228
--asset-path Path to assets and templates (default: <none>)
231-
-f, --force-non-ssl force allow use of non-ssl (default: false)
232-
--once generate the templates once and then exit (default: false)
233-
--skip-ping skip pinging the registry while establishing connection (default: false)
234-
--timeout timeout for HTTP requests (default: 1m0s)
229+
--auth-url alternate URL for registry authentication (ex. auth.docker.io) (default: <none>)
235230
--cert path to ssl cert (default: <none>)
231+
--clair url to clair instance (default: <none>)
236232
-d enable debug logging (default: false)
233+
-f, --force-non-ssl force allow use of non-ssl (default: false)
234+
--interval interval to generate new index.html's at (default: 1h0m0s)
235+
-k, --insecure do not verify tls certificates (default: false)
237236
--key path to ssl key (default: <none>)
237+
--listen-address address to listen on (default: <none>)
238+
--once generate the templates once and then exit (default: false)
239+
-p, --password password for the registry (default: <none>)
238240
--port port for server to run on (default: 8080)
239241
-r, --registry URL to the private registry (ex. r.j3ss.co) (default: <none>)
240-
--clair url to clair instance (default: <none>)
241-
-k, --insecure do not verify tls certificates (default: false)
242-
--interval interval to generate new index.html's at (default: 1h0m0s)
243-
-p, --password password for the registry (default: <none>)
242+
--skip-ping skip pinging the registry while establishing connection (default: false)
243+
--sort generate tag templates sorted by property (one of: created) (default: created)
244+
--timeout timeout for HTTP requests (default: 1m0s)
245+
-u, --username username for the registry (default: <none>)
244246
```
245247

246248
**Screenshots:**
@@ -283,4 +285,4 @@ against an insecure registry.
283285
**OR**
284286

285287
Run `make dind dtest` to avoid having to change your local docker config and
286-
to run the tests as docker-in-docker.
288+
to run the tests as docker-in-docker.

handlers.go

+17
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net/url"
1212
"os"
1313
"path/filepath"
14+
"sort"
1415
"strings"
1516
"sync"
1617
"time"
@@ -28,6 +29,7 @@ type registryController struct {
2829
l sync.Mutex
2930
tmpl *template.Template
3031
generateOnly bool
32+
repoSortBy string
3133
}
3234

3335
type v1Compatibility struct {
@@ -44,6 +46,16 @@ type Repository struct {
4446
VulnerabilityReport clair.VulnerabilityReport `json:"vulnerability"`
4547
}
4648

49+
const (
50+
sortByCreated = "created"
51+
)
52+
53+
type repoByDate []Repository
54+
55+
func (r repoByDate) Len() int { return len(r) }
56+
func (r repoByDate) Less(i, j int) bool { return r[i].Created.Before(r[j].Created) }
57+
func (r repoByDate) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
58+
4759
// An AnalysisResult holds all vulnerabilities of a scan
4860
type AnalysisResult struct {
4961
Repositories []Repository `json:"repositories"`
@@ -228,6 +240,11 @@ func (rc *registryController) generateTagsTemplate(ctx context.Context, repo str
228240
result.Repositories = append(result.Repositories, rp)
229241
}
230242

243+
switch rc.repoSortBy {
244+
case sortByCreated:
245+
sort.Sort(sort.Reverse(repoByDate(result.Repositories)))
246+
}
247+
231248
// Execute the template.
232249
var buf bytes.Buffer
233250
if err := rc.tmpl.ExecuteTemplate(&buf, "tags", result); err != nil {

server.go

+10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ func (cmd *serverCommand) Register(fs *flag.FlagSet) {
4343
fs.StringVar(&cmd.assetPath, "asset-path", "", "Path to assets and templates")
4444

4545
fs.BoolVar(&cmd.generateAndExit, "once", false, "generate the templates once and then exit")
46+
47+
sortOpts := []string{sortByCreated}
48+
fs.StringVar(&cmd.repoSortBy, "sort", sortByCreated,
49+
fmt.Sprintf("generate tag templates sorted by property (one of: %s)", strings.Join(sortOpts, ",")))
4650
}
4751

4852
type serverCommand struct {
@@ -57,6 +61,7 @@ type serverCommand struct {
5761
listenAddress string
5862
port string
5963
assetPath string
64+
repoSortBy string
6065
}
6166

6267
func (cmd *serverCommand) Run(ctx context.Context, args []string) error {
@@ -66,10 +71,15 @@ func (cmd *serverCommand) Run(ctx context.Context, args []string) error {
6671
return err
6772
}
6873

74+
if cmd.repoSortBy != sortByCreated {
75+
return fmt.Errorf("sort option invalid; '%s' is not valid", cmd.repoSortBy)
76+
}
77+
6978
// Create the registry controller for the handlers.
7079
rc := registryController{
7180
reg: r,
7281
generateOnly: cmd.generateAndExit,
82+
repoSortBy: cmd.repoSortBy,
7383
}
7484

7585
// Create a clair client if the user passed in a server address.

0 commit comments

Comments
 (0)