Merge with origin master

This commit is contained in:
hmwenchen 2016-04-22 09:18:51 +08:00
parent ab6bb58c36
commit dc96ded36a
5 changed files with 176 additions and 54 deletions

View File

@ -31,7 +31,6 @@ import (
type ProjectAPI struct {
BaseAPI
userID int
username string
projectID int64
}
@ -185,7 +184,6 @@ func (p *ProjectAPI) FilterAccessLog() {
}
p.Data["json"] = accessLogList
log.Errorf("--- accessLog first record: %v ---", accessLogList[0])
p.ServeJSON()
}

View File

@ -18,6 +18,7 @@ package api
import (
"encoding/json"
"net/http"
"os"
"strconv"
"strings"
"time"
@ -26,6 +27,9 @@ import (
"github.com/vmware/harbor/models"
svc_utils "github.com/vmware/harbor/service/utils"
"github.com/vmware/harbor/utils/log"
"github.com/vmware/harbor/utils/registry"
"github.com/vmware/harbor/utils/registry/auth"
"github.com/vmware/harbor/utils/registry/errors"
)
// RepositoryAPI handles request to /api/repositories /api/repositories/tags /api/repositories/manifests, the parm has to be put
@ -36,6 +40,7 @@ type RepositoryAPI struct {
BaseAPI
userID int
username string
registry *registry.Registry
}
// Prepare will set a non existent user ID in case the request tries to view repositories under a project he doesn't has permission.
@ -53,6 +58,43 @@ func (ra *RepositoryAPI) Prepare() {
} else {
ra.username = username
}
var client *http.Client
//no session, initialize a standard auth handler
if ra.userID == dao.NonExistUserID && len(ra.username) == 0 {
username, password, _ := ra.Ctx.Request.BasicAuth()
credential := auth.NewBasicAuthCredential(username, password)
client = registry.NewClientStandardAuthHandlerEmbeded(credential)
log.Debug("initializing standard auth handler")
} else {
// session works, initialize a username auth handler
username := ra.username
if len(username) == 0 {
user, err := dao.GetUser(models.User{
UserID: ra.userID,
})
if err != nil {
log.Errorf("error occurred whiling geting user for initializing a username auth handler: %v", err)
return
}
username = user.Username
}
client = registry.NewClientUsernameAuthHandlerEmbeded(username)
log.Debug("initializing username auth handler: %s", username)
}
endpoint := os.Getenv("REGISTRY_URL")
r, err := registry.New(endpoint, client)
if err != nil {
log.Fatalf("error occurred while initializing auth handler for repository API: %v", err)
}
ra.registry = r
}
// Get ...
@ -77,11 +119,13 @@ func (ra *RepositoryAPI) Get() {
ra.RenderError(http.StatusForbidden, "")
return
}
repoList, err := svc_utils.GetRepoFromCache()
if err != nil {
log.Errorf("Failed to get repo from cache, error: %v", err)
ra.RenderError(http.StatusInternalServerError, "internal sever error")
}
projectName := p.Name
q := ra.GetString("q")
var resp []string
@ -105,6 +149,56 @@ func (ra *RepositoryAPI) Get() {
ra.ServeJSON()
}
// Delete ...
func (ra *RepositoryAPI) Delete() {
repoName := ra.GetString("repo_name")
if len(repoName) == 0 {
ra.CustomAbort(http.StatusBadRequest, "repo_name is nil")
}
tags := []string{}
tag := ra.GetString("tag")
if len(tag) == 0 {
tagList, err := ra.registry.ListTag(repoName)
if err != nil {
e, ok := errors.ParseError(err)
if ok {
log.Info(e)
ra.CustomAbort(e.StatusCode, e.Message)
} else {
log.Error(err)
ra.CustomAbort(http.StatusInternalServerError, "internal error")
}
}
tags = append(tags, tagList...)
} else {
tags = append(tags, tag)
}
for _, t := range tags {
if err := ra.registry.DeleteTag(repoName, t); err != nil {
e, ok := errors.ParseError(err)
if ok {
ra.CustomAbort(e.StatusCode, e.Message)
} else {
log.Error(err)
ra.CustomAbort(http.StatusInternalServerError, "internal error")
}
}
log.Infof("delete tag: %s %s", repoName, t)
}
go func() {
log.Debug("refreshing catalog cache")
if err := svc_utils.RefreshCatalogCache(); err != nil {
log.Errorf("error occurred while refresh catalog cache: %v", err)
}
}()
}
type tag struct {
Name string `json:"name"`
Tags []string `json:"tags"`
@ -116,15 +210,18 @@ func (ra *RepositoryAPI) GetTags() {
var tags []string
repoName := ra.GetString("repo_name")
result, err := svc_utils.RegistryAPIGet(svc_utils.BuildRegistryURL(repoName, "tags", "list"), ra.username)
tags, err := ra.registry.ListTag(repoName)
if err != nil {
log.Errorf("Failed to get repo tags, repo name: %s, error: %v", repoName, err)
ra.RenderError(http.StatusInternalServerError, "Failed to get repo tags")
} else {
t := tag{}
json.Unmarshal(result, &t)
tags = t.Tags
e, ok := errors.ParseError(err)
if ok {
log.Info(e)
ra.CustomAbort(e.StatusCode, e.Message)
} else {
log.Error(err)
ra.CustomAbort(http.StatusInternalServerError, "internal error")
}
}
ra.Data["json"] = tags
ra.ServeJSON()
}
@ -136,14 +233,19 @@ func (ra *RepositoryAPI) GetManifests() {
item := models.RepoItem{}
result, err := svc_utils.RegistryAPIGet(svc_utils.BuildRegistryURL(repoName, "manifests", tag), ra.username)
_, _, payload, err := ra.registry.PullManifest(repoName, tag, registry.ManifestVersion1)
if err != nil {
log.Errorf("Failed to get manifests for repo, repo name: %s, tag: %s, error: %v", repoName, tag, err)
ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
return
e, ok := errors.ParseError(err)
if ok {
log.Info(e)
ra.CustomAbort(e.StatusCode, e.Message)
} else {
log.Error(err)
ra.CustomAbort(http.StatusInternalServerError, "internal error")
}
}
mani := models.Manifest{}
err = json.Unmarshal(result, &mani)
err = json.Unmarshal(payload, &mani)
if err != nil {
log.Errorf("Failed to decode json from response for manifests, repo name: %s, tag: %s, error: %v", repoName, tag, err)
ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
@ -157,7 +259,6 @@ func (ra *RepositoryAPI) GetManifests() {
ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
return
}
item.CreatedStr = item.Created.Format("2006-01-02 15:04:05")
item.DurationDays = strconv.Itoa(int(time.Since(item.Created).Hours()/24)) + " days"
ra.Data["json"] = item

View File

@ -40,7 +40,6 @@ type Target struct {
Digest string
Repository string
URL string `json:"Url"`
Tag string
}
// Actor holds information about actor.

View File

@ -29,7 +29,6 @@ type RepoItem struct {
ID string `json:"Id"`
Parent string `json:"Parent"`
Created time.Time `json:"Created"`
CreatedStr string `json:"CreatedStr"`
DurationDays string `json:"Duration Days"`
Author string `json:"Author"`
Architecture string `json:"Architecture"`

View File

@ -17,6 +17,8 @@ package service
import (
"encoding/json"
"net/http"
"os"
"regexp"
"sort"
"strings"
@ -25,6 +27,8 @@ import (
"github.com/vmware/harbor/models"
svc_utils "github.com/vmware/harbor/service/utils"
"github.com/vmware/harbor/utils/log"
"github.com/vmware/harbor/utils/registry"
"github.com/vmware/harbor/utils/registry/errors"
"github.com/astaxie/beego"
)
@ -32,11 +36,7 @@ import (
// NotificationHandler handles request on /service/notifications/, which listens to registry's events.
type NotificationHandler struct {
beego.Controller
}
type taglist struct {
Name string `json:"name"`
Tags []string `json:"tags"`
registry *registry.Registry
}
const manifestPattern = `^application/vnd.docker.distribution.manifest.v\d\+json`
@ -52,8 +52,9 @@ func (n *NotificationHandler) Post() {
log.Errorf("error while decoding json: %v", err)
return
}
var username, action, repo, project, repo_tag, tag_url string
var username, action, repo, project, repo_tag, tag_url, digest string
var matched bool
var client *http.Client
for _, e := range notification.Events {
matched, err = regexp.MatchString(manifestPattern, e.Target.MediaType)
if err != nil {
@ -65,15 +66,27 @@ func (n *NotificationHandler) Post() {
action = e.Action
repo = e.Target.Repository
tag_url = e.Target.URL
result, err1 := svc_utils.RegistryAPIGet(tag_url, username)
digest = e.Target.Digest
client = registry.NewClientUsernameAuthHandlerEmbeded(username)
log.Debug("initializing username auth handler: %s", username)
endpoint := os.Getenv("REGISTRY_URL")
r, err1 := registry.New(endpoint, client)
if err1 != nil {
log.Errorf("Failed to get manifests for repo, repo name: %s, tag: %s, error: %v", repo, tag_url, err1)
log.Fatalf("error occurred while initializing auth handler for repository API: %v", err1)
}
n.registry = r
_, _, payload, err2 := n.registry.PullManifest(repo, digest, registry.ManifestVersion1)
if err2 != nil {
log.Errorf("Failed to get manifests for repo, repo name: %s, tag: %s, error: %v", repo, tag_url, err2)
return
}
maniDig := models.ManifestDigest{}
err = json.Unmarshal(result, &maniDig)
err = json.Unmarshal(payload, &maniDig)
if err != nil {
log.Errorf("Failed to decode json from response for manifests, repo name: %s, tag: %s, error: %v", repo, tag_url, err)
return
@ -85,36 +98,48 @@ func (n *NotificationHandler) Post() {
digestLayers = append(digestLayers, diglayer.Digest)
}
result, err = svc_utils.RegistryAPIGet(svc_utils.BuildRegistryURL(repo, "tags", "list"), username)
tags, err := n.registry.ListTag(repo)
if err != nil {
log.Errorf("Failed to get repo tags, repo name: %s, error: %v", repo, err)
} else {
t := taglist{}
json.Unmarshal(result, &t)
for _, tag := range t.Tags {
result, err = svc_utils.RegistryAPIGet(svc_utils.BuildRegistryURL(repo, "manifests", tag), username)
if err != nil {
log.Errorf("Failed to get repo tags, repo name: %s, error: %v", repo, err)
continue
}
taginfo := models.Manifest{}
err = json.Unmarshal(result, &taginfo)
if err != nil {
log.Errorf("Failed to decode json from response for manifests, repo name: %s, tag: %s, error: %v", repo, tag, err)
continue
}
for _, fslayer := range taginfo.FsLayers {
tagLayers = append(tagLayers, fslayer.BlobSum)
}
sort.Strings(digestLayers)
sort.Strings(tagLayers)
eq := compStringArray(digestLayers, tagLayers)
if eq {
repo_tag = tag
break
}
e, ok := errors.ParseError(err)
if ok {
log.Info(e)
} else {
log.Error(err)
}
return
}
log.Infof("tags : %v ", tags)
for _, tag := range tags {
_, _, payload, err := n.registry.PullManifest(repo, tag, registry.ManifestVersion1)
if err != nil {
e, ok := errors.ParseError(err)
if ok {
log.Info(e)
} else {
log.Error(err)
}
continue
}
taginfo := models.Manifest{}
err = json.Unmarshal(payload, &taginfo)
if err != nil {
log.Errorf("Failed to decode json from response for manifests, repo name: %s, tag: %s, error: %v", repo, tag, err)
continue
}
for _, fslayer := range taginfo.FsLayers {
tagLayers = append(tagLayers, fslayer.BlobSum)
}
sort.Strings(digestLayers)
sort.Strings(tagLayers)
eq := compStringArray(digestLayers, tagLayers)
if eq {
repo_tag = tag
break
}
}
if strings.Contains(repo, "/") {