Skip to content

Commit

Permalink
feat(server): implement tags/list endpoint
Browse files Browse the repository at this point in the history
When a git source is used branch names are exposed in the tags list.

For other source types, only "latest" is exposed.

Fixes: #85
  • Loading branch information
eonpatapon committed Feb 27, 2020
1 parent 9292851 commit cd155b0
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
35 changes: 33 additions & 2 deletions config/pkgsource.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

Expand All @@ -32,13 +33,16 @@ type PkgSource interface {
// for calling Nix.
Render(tag string) (string, string)

// Create a key by which builds for this source and iamge
// Create a key by which builds for this source and image
// combination can be cached.
//
// The empty string means that this value is not cacheable due
// to the package source being a moving target (such as a
// channel).
CacheKey(pkgs []string, tag string) string

// Return available docker tags for the current PkgSource
Tags() ([]string, error)
}

type GitSource struct {
Expand Down Expand Up @@ -91,6 +95,25 @@ func (g *GitSource) CacheKey(pkgs []string, tag string) string {
return hashed
}

// Regex to determine valid docker tags
var tagRegex = regexp.MustCompile(`^[\w][\w.-]{0,127}$`)

func (g *GitSource) Tags() ([]string, error) {
tags := []string{"latest"}
heads := filepath.Join(g.repository, ".git/refs/heads")
err := filepath.Walk(heads, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
// latest tag is always present and represent the master branch
if tagRegex.MatchString(info.Name()) && info.Name() != "master" {
tags = append(tags, info.Name())
}
return nil
})
return tags, err
}

type NixChannel struct {
channel string
}
Expand All @@ -113,6 +136,10 @@ func (n *NixChannel) CacheKey(pkgs []string, tag string) string {
return hashed
}

func (n *NixChannel) Tags() ([]string, error) {
return []string{"latest"}, nil
}

type PkgsPath struct {
path string
}
Expand All @@ -128,6 +155,10 @@ func (p *PkgsPath) CacheKey(pkgs []string, tag string) string {
return ""
}

func (n *PkgsPath) Tags() ([]string, error) {
return []string{"latest"}, nil
}

// Retrieve a package source from the environment. If no source is
// specified, the Nix code will default to a recent NixOS channel.
func pkgSourceFromEnv() (PkgSource, error) {
Expand All @@ -140,7 +171,7 @@ func pkgSourceFromEnv() (PkgSource, error) {
}

if git := os.Getenv("NIXERY_PKGS_REPO"); git != "" {
log.WithField("repo", git).Info("using NIx package set from git repository")
log.WithField("repo", git).Info("using Nix package set from git repository")

return &GitSource{
repository: git,
Expand Down
22 changes: 22 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ var version string = "devel"
var (
manifestRegex = regexp.MustCompile(`^/v2/([\w|\-|\.|\_|\/]+)/manifests/([\w|\-|\.|\_]+)$`)
layerRegex = regexp.MustCompile(`^/v2/([\w|\-|\.|\_|\/]+)/blobs/sha256:(\w+)$`)
tagsRegex = regexp.MustCompile(`^/v2/([\w|\-|\.|\_|\/]+)/tags/list$`)
)

// Downloads the popularity information for the package set from the
Expand Down Expand Up @@ -184,6 +185,27 @@ func (h *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

tagsMatches := tagsRegex.FindStringSubmatch(r.RequestURI)
if len(tagsMatches) == 2 {
tags, err := h.state.Cfg.Pkgs.Tags()
if err != nil {
writeError(w, 500, "UNKNOWN", "failed to list tags")

log.WithError(err).WithFields(log.Fields{
"image": tagsMatches[1],
}).Error(err)

return
}
manifest, _ := json.Marshal(map[string]interface{}{
"name": tagsMatches[1],
"tags": tags,
})
w.Header().Add("Content-Type", manifestMediaType)
w.Write(manifest)
return
}

log.WithField("uri", r.RequestURI).Info("unsupported registry route")

w.WriteHeader(404)
Expand Down

0 comments on commit cd155b0

Please sign in to comment.