add comments to pass golint

This commit is contained in:
Tan Jiang 2016-02-26 18:35:55 +08:00
parent 415dc84560
commit 4a24d642b7
23 changed files with 147 additions and 61 deletions

View File

@ -24,18 +24,22 @@ import (
"github.com/astaxie/beego"
)
// BaseAPI wraps common methods for controllers to host API
type BaseAPI struct {
beego.Controller
}
// Render returns nil as it won't render template
func (b *BaseAPI) Render() error {
return nil
}
// RenderError provides shortcut to render http error
func (b *BaseAPI) RenderError(code int, text string) {
http.Error(b.Ctx.ResponseWriter, text, code)
}
// DecodeJSONReq decodes a json request
func (b *BaseAPI) DecodeJSONReq(v interface{}) {
err := json.Unmarshal(b.Ctx.Input.CopyBody(1<<32), v)
if err != nil {
@ -44,6 +48,7 @@ func (b *BaseAPI) DecodeJSONReq(v interface{}) {
}
}
// ValidateUser checks if the request triggered by a valid user
func (b *BaseAPI) ValidateUser() int {
sessionUserID := b.GetSession("userId")

View File

@ -24,6 +24,7 @@ import (
"github.com/astaxie/beego"
)
// ProjectMemberAPI handles request to /api/projects/{}/members/{}
type ProjectMemberAPI struct {
BaseAPI
memberID int
@ -37,6 +38,7 @@ type memberReq struct {
Roles []int `json:"roles"`
}
// Prepare validates the URL and parms
func (pma *ProjectMemberAPI) Prepare() {
pid, err := strconv.ParseInt(pma.Ctx.Input.Param(":pid"), 10, 64)
if err != nil {
@ -71,9 +73,10 @@ func (pma *ProjectMemberAPI) Prepare() {
}
}
// Get ...
func (pma *ProjectMemberAPI) Get() {
pid := pma.project.ProjectID
if !CheckProjectPermission(pma.currentUserID, pid) {
if !checkProjectPermission(pma.currentUserID, pid) {
beego.Warning("Current user, user id :", pma.currentUserID, "does not have permission for project, id:", pid)
pma.RenderError(http.StatusForbidden, "")
return
@ -109,6 +112,7 @@ func (pma *ProjectMemberAPI) Get() {
pma.ServeJSON()
}
// Post ...
func (pma *ProjectMemberAPI) Post() {
pid := pma.project.ProjectID
userQuery := models.User{UserID: pma.currentUserID, RoleID: models.PROJECTADMIN}
@ -125,7 +129,7 @@ func (pma *ProjectMemberAPI) Post() {
var req memberReq
pma.DecodeJSONReq(&req)
username := req.Username
userID := CheckUserExists(username)
userID := checkUserExists(username)
if userID <= 0 {
beego.Warning("User does not exist, user name:", username)
pma.RenderError(http.StatusNotFound, "User does not exist")
@ -152,6 +156,7 @@ func (pma *ProjectMemberAPI) Post() {
}
}
// Put ...
func (pma *ProjectMemberAPI) Put() {
pid := pma.project.ProjectID
mid := pma.memberID
@ -193,6 +198,7 @@ func (pma *ProjectMemberAPI) Put() {
}
}
// Delete ...
func (pma *ProjectMemberAPI) Delete() {
pid := pma.project.ProjectID
mid := pma.memberID

View File

@ -28,6 +28,7 @@ import (
"github.com/astaxie/beego"
)
// ProjectAPI handles request to /api/projects/{} /api/projects/{}/logs
type ProjectAPI struct {
BaseAPI
userID int
@ -41,6 +42,7 @@ type projectReq struct {
const projectNameMaxLen int = 30
// Prepare validates the URL and the user
func (p *ProjectAPI) Prepare() {
p.userID = p.ValidateUser()
idStr := p.Ctx.Input.Param(":id")
@ -62,6 +64,7 @@ func (p *ProjectAPI) Prepare() {
}
}
// Post ...
func (p *ProjectAPI) Post() {
var req projectReq
var public int
@ -92,6 +95,7 @@ func (p *ProjectAPI) Post() {
}
}
// Head ...
func (p *ProjectAPI) Head() {
projectName := p.GetString("project_name")
result, err := dao.ProjectExists(projectName)
@ -106,6 +110,7 @@ func (p *ProjectAPI) Head() {
}
}
// Get ...
func (p *ProjectAPI) Get() {
queryProject := models.Project{UserID: p.userID}
projectName := p.GetString("project_name")
@ -129,6 +134,7 @@ func (p *ProjectAPI) Get() {
p.ServeJSON()
}
// Put ...
func (p *ProjectAPI) Put() {
var req projectReq
var public int
@ -156,6 +162,7 @@ func (p *ProjectAPI) Put() {
}
}
// FilterAccessLog handles GET to /api/projects/{}/logs
func (p *ProjectAPI) FilterAccessLog() {
var filter models.AccessLog

View File

@ -28,15 +28,17 @@ import (
"github.com/astaxie/beego"
)
//For repostiories, we won't check the session in this API due to search functionality, querying manifest will be contorlled by
//the security of registry
// RepositoryAPI handles request to /api/repositories /api/repositories/tags /api/repositories/manifests, the parm has to be put
// in the query string as the web framework can not parse the URL if it contains veriadic sectors.
// For repostiories, we won't check the session in this API due to search functionality, querying manifest will be contorlled by
// the security of registry
type RepositoryAPI struct {
BaseAPI
userID int
username string
}
// Prepare will set a non existent user ID in case the request tries to view repositories under a project he doesn't has permission.
func (ra *RepositoryAPI) Prepare() {
userID, ok := ra.GetSession("userId").(int)
if !ok {
@ -53,6 +55,7 @@ func (ra *RepositoryAPI) Prepare() {
}
}
// Get ...
func (ra *RepositoryAPI) Get() {
projectID, err0 := ra.GetInt64("project_id")
if err0 != nil {
@ -70,7 +73,7 @@ func (ra *RepositoryAPI) Get() {
ra.RenderError(http.StatusNotFound, "")
return
}
if p.Public == 0 && !CheckProjectPermission(ra.userID, projectID) {
if p.Public == 0 && !checkProjectPermission(ra.userID, projectID) {
ra.RenderError(http.StatusForbidden, "")
return
}
@ -102,23 +105,24 @@ func (ra *RepositoryAPI) Get() {
ra.ServeJSON()
}
type Tag struct {
type tag struct {
Name string `json:"name"`
Tags []string `json:"tags"`
}
type HistroyItem struct {
type histroyItem struct {
V1Compatibility string `json:"v1Compatibility"`
}
type Manifest struct {
type manifest struct {
Name string `json:"name"`
Tag string `json:"tag"`
Architecture string `json:"architecture"`
SchemaVersion int `json:"schemaVersion"`
History []HistroyItem `json:"history"`
History []histroyItem `json:"history"`
}
// GetTags handles GET /api/repositories/tags
func (ra *RepositoryAPI) GetTags() {
var tags []string
@ -129,7 +133,7 @@ func (ra *RepositoryAPI) GetTags() {
beego.Error("Failed to get repo tags, repo name:", repoName, ", error: ", err)
ra.RenderError(http.StatusInternalServerError, "Failed to get repo tags")
} else {
t := Tag{}
t := tag{}
json.Unmarshal(result, &t)
tags = t.Tags
}
@ -137,6 +141,7 @@ func (ra *RepositoryAPI) GetTags() {
ra.ServeJSON()
}
// GetManifests handles GET /api/repositories/manifests
func (ra *RepositoryAPI) GetManifests() {
repoName := ra.GetString("repo_name")
tag := ra.GetString("tag")
@ -149,7 +154,7 @@ func (ra *RepositoryAPI) GetManifests() {
ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
return
}
mani := Manifest{}
mani := manifest{}
err = json.Unmarshal(result, &mani)
if err != nil {
beego.Error("Failed to decode json from response for manifests, repo name:", repoName, ", tag:", tag, ", error:", err)

View File

@ -27,15 +27,17 @@ import (
"github.com/astaxie/beego"
)
// SearchAPI handles requesst to /api/search
type SearchAPI struct {
BaseAPI
}
type SearchResult struct {
type searchResult struct {
Project []map[string]interface{} `json:"project"`
Repository []map[string]interface{} `json:"repository"`
}
// Get ...
func (n *SearchAPI) Get() {
userID, ok := n.GetSession("userId").(int)
if !ok {
@ -71,7 +73,7 @@ func (n *SearchAPI) Get() {
}
sort.Strings(repositories)
repositoryResult := filterRepositories(repositories, projects, keyword)
result := &SearchResult{Project: projectResult, Repository: repositoryResult}
result := &searchResult{Project: projectResult, Repository: repositoryResult}
n.Data["json"] = result
n.ServeJSON()
}

View File

@ -24,12 +24,14 @@ import (
"github.com/astaxie/beego"
)
// UserAPI handles request to /api/users/{}
type UserAPI struct {
BaseAPI
currentUserID int
userID int
}
// Prepare validates the URL and parms
func (ua *UserAPI) Prepare() {
ua.currentUserID = ua.ValidateUser()
@ -56,6 +58,7 @@ func (ua *UserAPI) Prepare() {
}
}
// Get ...
func (ua *UserAPI) Get() {
exist, err := dao.IsAdminRole(ua.currentUserID)
if err != nil {
@ -98,6 +101,7 @@ func (ua *UserAPI) Get() {
ua.ServeJSON()
}
// Put ...
func (ua *UserAPI) Put() { //currently only for toggle admin, so no request body
exist, err := dao.IsAdminRole(ua.currentUserID)
if err != nil {
@ -113,6 +117,7 @@ func (ua *UserAPI) Put() { //currently only for toggle admin, so no request body
dao.ToggleUserAdminRole(userQuery)
}
// Delete ...
func (ua *UserAPI) Delete() {
exist, err := dao.IsAdminRole(ua.currentUserID)
if err != nil {

View File

@ -21,7 +21,7 @@ import (
"github.com/astaxie/beego"
)
func CheckProjectPermission(userID int, projectID int64) bool {
func checkProjectPermission(userID int, projectID int64) bool {
exist, err := dao.IsAdminRole(userID)
if err != nil {
beego.Error("Error occurred in IsAdminRole:", err)
@ -38,7 +38,7 @@ func CheckProjectPermission(userID int, projectID int64) bool {
return len(roleList) > 0
}
func CheckUserExists(name string) int {
func checkUserExists(name string) int {
u, err := dao.GetUser(models.User{Username: name})
if err != nil {
beego.Error("Error occurred in GetUser:", err)

View File

@ -24,12 +24,16 @@ import (
"github.com/astaxie/beego"
)
// Authenticator provides interface to authenticate user credentials.
type Authenticator interface {
// Authenticate ...
Authenticate(m models.AuthModel) (*models.User, error)
}
var registry = make(map[string]Authenticator)
// Register add different authenticators to registry map.
func Register(name string, authenticator Authenticator) {
if _, dup := registry[name]; dup {
log.Printf("authenticator: %s has been registered", name)
@ -38,6 +42,7 @@ func Register(name string, authenticator Authenticator) {
registry[name] = authenticator
}
// Login authenticates user credentials based on setting.
func Login(m models.AuthModel) (*models.User, error) {
var authMode = os.Getenv("AUTH_MODE")

View File

@ -20,8 +20,10 @@ import (
"github.com/vmware/harbor/models"
)
// Auth implements Authenticator interface to authenticate user against DB.
type Auth struct{}
// Authenticate calls dao to authenticate user.
func (d *Auth) Authenticate(m models.AuthModel) (*models.User, error) {
u, err := dao.LoginByDb(m)
if err != nil {

View File

@ -29,10 +29,14 @@ import (
"github.com/mqu/openldap"
)
// Auth implements Authenticator interface to authenticate against LDAP
type Auth struct{}
const metaChars = "&|!=~*<>()"
// Authenticate checks user's credential agains LDAP based on basedn template and LDAP URL,
// if the check is successful a dummy record will be insert into DB, such that this user can
// be associated to other entities in the system.
func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) {
ldapURL := os.Getenv("LDAP_URL")

View File

@ -23,14 +23,17 @@ import (
"github.com/beego/i18n"
)
// CommonControler handles request from UI that doesn't expect a page, such as /login /logout ...
type CommonController struct {
BaseController
}
// Render returns nil.
func (c *CommonController) Render() error {
return nil
}
// BaseController wraps common methods such as i18n support, forward, which can be leveraged by other UI render controllers.
type BaseController struct {
beego.Controller
i18n.Locale
@ -47,6 +50,7 @@ const (
var supportLanguages map[string]langType
// Prepare extracts the language information from request and populate data for rendering templates.
func (b *BaseController) Prepare() {
var lang string
@ -99,6 +103,7 @@ func (b *BaseController) Prepare() {
b.Data["AuthMode"] = authMode
}
// ForwardTo setup layout and template for content for a page.
func (b *BaseController) ForwardTo(pageTitle string, pageName string) {
b.Layout = "segment/base-layout.tpl"
b.TplName = "segment/base-layout.tpl"

View File

@ -25,10 +25,13 @@ import (
"github.com/astaxie/beego"
)
// ItemDetailController handles requet to /registry/detail, which shows the detail of a project.
type ItemDetailController struct {
BaseController
}
// Get will check if user has permission to view a certain project, if not user will be redirected to signin or his homepage.
// If the check is passed it renders the project detail page.
func (idc *ItemDetailController) Get() {
projectID, _ := idc.GetInt64("project_id")

View File

@ -23,23 +23,28 @@ import (
"github.com/astaxie/beego"
)
// IndexController handles request to /
type IndexController struct {
BaseController
}
// Get renders the index page.
func (c *IndexController) Get() {
c.Data["Username"] = c.GetSession("username")
c.ForwardTo("page_title_index", "index")
}
// SignInController handles request to /signIn
type SignInController struct {
BaseController
}
// Get renders Sign In page.
func (sic *SignInController) Get() {
sic.ForwardTo("page_title_sign_in", "sign-in")
}
// Login handles login request from UI.
func (c *CommonController) Login() {
principal := c.GetString("principal")
password := c.GetString("password")
@ -58,6 +63,7 @@ func (c *CommonController) Login() {
c.SetSession("username", user.Username)
}
// SwitchLanguage handles UI request to switch between different languages and re-render template based on language.
func (c *CommonController) SwitchLanguage() {
lang := c.GetString("lang")
if lang == "en-US" || lang == "zh-CN" {
@ -67,6 +73,7 @@ func (c *CommonController) SwitchLanguage() {
c.Redirect(c.Ctx.Request.Header.Get("Referer"), http.StatusFound)
}
// Logout handles UI request to logout.
func (c *CommonController) Logout() {
c.DestroySession()
}

View File

@ -28,10 +28,12 @@ import (
"github.com/astaxie/beego"
)
// ChangePasswordController handles request to /changePassword
type ChangePasswordController struct {
BaseController
}
// Get renders the page for user to change password.
func (cpc *ChangePasswordController) Get() {
sessionUserID := cpc.GetSession("userId")
if sessionUserID == nil {
@ -42,6 +44,7 @@ func (cpc *ChangePasswordController) Get() {
cpc.ForwardTo("page_title_change_password", "change-password")
}
// UpdatePassword handles UI request to update user's password, it only works when the auth mode is db_auth.
func (cc *CommonController) UpdatePassword() {
sessionUserID := cc.GetSession("userId")
@ -82,20 +85,23 @@ func (cc *CommonController) UpdatePassword() {
}
}
// ForgotPasswordController handles request to /forgotPassword
type ForgotPasswordController struct {
BaseController
}
type MessageDetail struct {
// Get Renders the page for user to input Email to reset password.
func (fpc *ForgotPasswordController) Get() {
fpc.ForwardTo("page_title_forgot_password", "forgot-password")
}
type messageDetail struct {
Hint string
URL string
UUID string
}
func (fpc *ForgotPasswordController) Get() {
fpc.ForwardTo("page_title_forgot_password", "forgot-password")
}
// SendEmail verifies the Email address and contact SMTP server to send reset password Email.
func (cc *CommonController) SendEmail() {
email := cc.GetString("email")
@ -133,7 +139,7 @@ func (cc *CommonController) SendEmail() {
beego.Error("Error occurred in GenerateRandomString:", err)
cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
}
err = messageTemplate.Execute(message, MessageDetail{
err = messageTemplate.Execute(message, messageDetail{
Hint: cc.Tr("reset_email_hint"),
URL: harborURL,
UUID: uuid,
@ -170,10 +176,12 @@ func (cc *CommonController) SendEmail() {
}
// ResetPasswordController handles request to /resetPassword
type ResetPasswordController struct {
BaseController
}
// Get checks if reset_uuid in the reset link is valid and render the result page for user to reset password.
func (rpc *ResetPasswordController) Get() {
resetUUID := rpc.GetString("reset_uuid")
@ -198,6 +206,7 @@ func (rpc *ResetPasswordController) Get() {
}
}
// ResetPassword handles request from the reset page and reset password
func (cc *CommonController) ResetPassword() {
resetUUID := cc.GetString("reset_uuid")

View File

@ -1,23 +1,25 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
// ProjectController handles request to /registry/project
type ProjectController struct {
BaseController
}
// Get renders project page.
func (p *ProjectController) Get() {
p.Data["Username"] = p.GetSession("username")
p.ForwardTo("page_title_project", "project")

View File

@ -25,10 +25,12 @@ import (
"github.com/astaxie/beego"
)
// RegisterController handles request to /register
type RegisterController struct {
BaseController
}
// Get renders the Sign In page, it only works if the auth mode is set to db_auth
func (rc *RegisterController) Get() {
authMode := os.Getenv("AUTH_MODE")
if authMode == "" || authMode == "db_auth" {
@ -38,6 +40,7 @@ func (rc *RegisterController) Get() {
}
}
// SignUp insert data into DB based on data in form.
func (rc *CommonController) SignUp() {
username := strings.TrimSpace(rc.GetString("username"))
email := strings.TrimSpace(rc.GetString("email"))
@ -54,6 +57,7 @@ func (rc *CommonController) SignUp() {
}
}
// UserExists checks if user exists when user input value in sign in form.
func (rc *CommonController) UserExists() {
target := rc.GetString("target")
value := rc.GetString("value")

View File

@ -1,23 +1,25 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
// SearchController handles request to /search
type SearchController struct {
BaseController
}
// Get renders page for displaying search result.
func (sc *SearchController) Get() {
sc.Data["Username"] = sc.GetSession("username")
sc.Data["QueryParam"] = sc.GetString("q")

View File

@ -61,5 +61,5 @@ func init() {
//external service that hosted on harbor process:
beego.Router("/service/notifications", &service.NotificationHandler{})
beego.Router("/service/token", &service.AuthController{}, "get:Auth")
beego.Router("/service/token", &service.TokenHandler{})
}

View File

@ -25,12 +25,14 @@ import (
"github.com/astaxie/beego"
)
// NotificationHandler handles request on /service/notifications/, which listens to registry's events.
type NotificationHandler struct {
beego.Controller
}
const MediaTypeManifest = "application/vnd.docker.distribution.manifest.v1+json"
const mediaTypeManifest = "application/vnd.docker.distribution.manifest.v1+json"
// Post handles POST request, and records audit log or refreshes cache based on event.
func (n *NotificationHandler) Post() {
var notification models.Notification
// log.Printf("Notification Handler triggered!\n")
@ -43,7 +45,7 @@ func (n *NotificationHandler) Post() {
}
var username, action, repo, project string
for _, e := range notification.Events {
if e.Target.MediaType == MediaTypeManifest && strings.HasPrefix(e.Request.UserAgent, "docker") {
if e.Target.MediaType == mediaTypeManifest && strings.HasPrefix(e.Request.UserAgent, "docker") {
username = e.Actor.Name
action = e.Action
repo = e.Target.Repository
@ -67,6 +69,7 @@ func (n *NotificationHandler) Post() {
}
// Render returns nil as it won't render any template.
func (n *NotificationHandler) Render() error {
return nil
}

View File

@ -27,12 +27,15 @@ import (
"github.com/docker/distribution/registry/auth/token"
)
type AuthController struct {
// TokenHandler handles request on /service/token, which is the auth provider for registry.
type TokenHandler struct {
beego.Controller
}
//handle request
func (a *AuthController) Auth() {
// Get handles GET request, it checks the http header for user credentials
// and parse service and scope based on docker registry v2 standard,
// checkes the permission agains local DB and generates jwt token.
func (a *TokenHandler) Get() {
request := a.Ctx.Request
@ -56,7 +59,7 @@ func (a *AuthController) Auth() {
a.serveToken(username, service, access)
}
func (a *AuthController) serveToken(username, service string, access []*token.ResourceActions) {
func (a *TokenHandler) serveToken(username, service string, access []*token.ResourceActions) {
writer := a.Ctx.ResponseWriter
//create token
rawToken, err := svc_utils.MakeToken(username, service, access)

View File

@ -36,6 +36,7 @@ const (
expiration = 5 //minute
)
// GetResourceActions ...
func GetResourceActions(scope string) []*token.ResourceActions {
var res []*token.ResourceActions
if scope == "" {
@ -50,9 +51,8 @@ func GetResourceActions(scope string) []*token.ResourceActions {
return res
}
//Try to modify the action list in access based on permission
//determine if the request needs to be authenticated.
//for details see:https://github.com/docker/docker/issues/15640
// FilterAccess modify the action list in access based on permission
// determine if the request needs to be authenticated.
func FilterAccess(username string, authenticated bool, a *token.ResourceActions) {
if a.Type == "registry" && a.Name == "catalog" {
@ -98,7 +98,7 @@ func FilterAccess(username string, authenticated bool, a *token.ResourceActions)
log.Printf("current access, type: %s, name:%s, actions:%v \n", a.Type, a.Name, a.Actions)
}
//For the UI process to call, so it won't establish a https connection from UI to proxy.
// GenTokenForUI is for the UI process to call, so it won't establish a https connection from UI to proxy.
func GenTokenForUI(username, service, scope string) (string, error) {
access := GetResourceActions(scope)
for _, a := range access {
@ -107,6 +107,7 @@ func GenTokenForUI(username, service, scope string) (string, error) {
return MakeToken(username, service, access)
}
// MakeToken makes a valid jwt token based on parms.
func MakeToken(username, service string, access []*token.ResourceActions) (string, error) {
pk, err := libtrust.LoadKeyFile(privateKey)
if err != nil {

View File

@ -25,9 +25,10 @@ import (
"github.com/astaxie/beego/cache"
)
// Cache is the global cache in system.
var Cache cache.Cache
const CATALOG string = "catalog"
const catalogKey string = "catalog"
func init() {
var err error
@ -37,6 +38,7 @@ func init() {
}
}
// RefreshCatalogCache calls registry's API to get repository list and write it to cache.
func RefreshCatalogCache() error {
result, err := RegistryAPIGet(BuildRegistryURL("_catalog"), "")
if err != nil {
@ -47,19 +49,20 @@ func RefreshCatalogCache() error {
if err != nil {
return err
}
Cache.Put(CATALOG, repoResp.Repositories, 600*time.Second)
Cache.Put(catalogKey, repoResp.Repositories, 600*time.Second)
return nil
}
// GetRepoFromCache get repository list from cache, it refreshes the cache if it's empty.
func GetRepoFromCache() ([]string, error) {
result := Cache.Get(CATALOG)
result := Cache.Get(catalogKey)
if result == nil {
err := RefreshCatalogCache()
if err != nil {
return nil, err
}
cached := Cache.Get(CATALOG)
cached := Cache.Get(catalogKey)
if cached != nil {
return cached.([]string), nil
}

View File

@ -24,6 +24,7 @@ import (
"strings"
)
// BuildRegistryURL ...
func BuildRegistryURL(segments ...string) string {
registryURL := os.Getenv("REGISTRY_URL")
if registryURL == "" {
@ -40,6 +41,8 @@ func BuildRegistryURL(segments ...string) string {
return url
}
// RegistryAPIGet triggers GET request to the URL which is the endpoint of registry and returns the response body.
// It will attach a valid jwt token to the request if registry requires.
func RegistryAPIGet(url, username string) ([]byte, error) {
response, err := http.Get(url)
if err != nil {