mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-16 20:01:35 +01:00
Add api to get namespaces of registry
To query the namespace of the registry according to its ID. Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
parent
68342c68bc
commit
117c36d52c
@ -2291,6 +2291,39 @@ paths:
|
||||
description: Registry not found
|
||||
'500':
|
||||
description: Unexpected internal errors.
|
||||
/registries/{id}/namespace:
|
||||
get:
|
||||
summary: List namespaces of registry
|
||||
description: |
|
||||
This endpoint let user list namespaces of registry according to query.
|
||||
parameters:
|
||||
- name: id
|
||||
in: query
|
||||
type: integer
|
||||
required: true
|
||||
description: The registry ID.
|
||||
- name: name
|
||||
in: query
|
||||
type: string
|
||||
required: false
|
||||
description: The name of namespace.
|
||||
tags:
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Namespace'
|
||||
'401':
|
||||
description: User need to login first.
|
||||
'404':
|
||||
description: No registry found.
|
||||
'403':
|
||||
description: User has no privilege for the operation.
|
||||
'500':
|
||||
description: Unexpected internal errors.
|
||||
/internal/syncregistry:
|
||||
post:
|
||||
summary: Sync repositories from registry to DB.
|
||||
@ -4965,4 +4998,14 @@ definitions:
|
||||
description: The start time
|
||||
end_time:
|
||||
type: string
|
||||
description: The end time
|
||||
description: The end time
|
||||
Namespace:
|
||||
type: object
|
||||
description: The namespace of registry
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The name of namespace
|
||||
metadata:
|
||||
type: object
|
||||
description: The metadata of namespace
|
@ -321,6 +321,60 @@ func (t *RegistryAPI) GetInfo() {
|
||||
t.WriteJSONData(process(info))
|
||||
}
|
||||
|
||||
// GetNamespace get the namespace of a registry
|
||||
func (t *RegistryAPI) GetNamespace() {
|
||||
var registry *model.Registry
|
||||
var err error
|
||||
|
||||
id, err := t.GetInt64FromPath(":id")
|
||||
if err != nil || id < 0 {
|
||||
t.HandleBadRequest(fmt.Sprintf("invalid registry ID %s", t.GetString(":id")))
|
||||
return
|
||||
}
|
||||
if id > 0 {
|
||||
registry, err = t.manager.Get(id)
|
||||
if err != nil {
|
||||
t.HandleInternalServerError(fmt.Sprintf("failed to get registry %d: %v", id, err))
|
||||
return
|
||||
}
|
||||
} else if id == 0 {
|
||||
registry = event.GetLocalRegistry()
|
||||
}
|
||||
|
||||
if registry == nil {
|
||||
t.HandleNotFound(fmt.Sprintf("registry %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
if !adapter.HasFactory(registry.Type) {
|
||||
t.HandleInternalServerError(fmt.Sprintf("no adapter factory found for %s", registry.Type))
|
||||
return
|
||||
}
|
||||
|
||||
regFactory, err := adapter.GetFactory(registry.Type)
|
||||
if err != nil {
|
||||
t.HandleInternalServerError(fmt.Sprintf("fail to get adapter factory %s", registry.Type))
|
||||
return
|
||||
}
|
||||
regAdapter, err := regFactory(registry)
|
||||
if err != nil {
|
||||
t.HandleInternalServerError(fmt.Sprintf("fail to get adapter %s", registry.Type))
|
||||
return
|
||||
}
|
||||
|
||||
query := &model.NamespaceQuery{
|
||||
Name: t.GetString("name"),
|
||||
}
|
||||
npResults, err := regAdapter.ListNamespaces(query)
|
||||
if err != nil {
|
||||
t.HandleInternalServerError(fmt.Sprintf("fail to list namespaces %s %v", registry.Type, err))
|
||||
return
|
||||
}
|
||||
|
||||
t.Data["json"] = npResults
|
||||
t.ServeJSON()
|
||||
}
|
||||
|
||||
// merge "SupportedResourceTypes" into "SupportedResourceFilters" for UI to render easier
|
||||
func process(info *model.RegistryInfo) *model.RegistryInfo {
|
||||
if info == nil {
|
||||
|
@ -135,6 +135,7 @@ func initRouters() {
|
||||
beego.Router("/api/registries/ping", &api.RegistryAPI{}, "post:Ping")
|
||||
// we use "0" as the ID of the local Harbor registry, so don't add "([0-9]+)" in the path
|
||||
beego.Router("/api/registries/:id/info", &api.RegistryAPI{}, "get:GetInfo")
|
||||
beego.Router("/api/registries/:id/namespace", &api.RegistryAPI{}, "get:GetNamespace")
|
||||
|
||||
beego.Router("/v2/*", &controllers.RegistryProxy{}, "*:Handle")
|
||||
|
||||
|
@ -125,10 +125,24 @@ func (a *adapter) Info() (*model.RegistryInfo, error) {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// TODO implement the function
|
||||
func (a *adapter) ListNamespaces(*model.NamespaceQuery) ([]*model.Namespace, error) {
|
||||
return nil, nil
|
||||
func (a *adapter) ListNamespaces(npQuery *model.NamespaceQuery) ([]*model.Namespace, error) {
|
||||
var nps []*model.Namespace
|
||||
projects, err := a.getProjects(npQuery.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pro := range projects {
|
||||
nps = append(nps, &model.Namespace{
|
||||
Name: pro.Name,
|
||||
Metadata: pro.Metadata,
|
||||
})
|
||||
}
|
||||
|
||||
return nps, nil
|
||||
|
||||
}
|
||||
|
||||
func (a *adapter) ConvertResourceMetadata(metadata *model.ResourceMetadata, namespace *model.Namespace) (*model.ResourceMetadata, error) {
|
||||
if metadata == nil {
|
||||
return nil, errors.New("the metadata cannot be null")
|
||||
@ -237,13 +251,21 @@ type project struct {
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
func (a *adapter) getProject(name string) (*project, error) {
|
||||
// TODO need an API to exact match project by name
|
||||
func (a *adapter) getProjects(name string) ([]*project, error) {
|
||||
projects := []*project{}
|
||||
url := fmt.Sprintf("%s/api/projects?name=%s&page=1&page_size=1000", a.coreServiceURL, name)
|
||||
if err := a.client.Get(url, &projects); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projects, nil
|
||||
}
|
||||
|
||||
func (a *adapter) getProject(name string) (*project, error) {
|
||||
// TODO need an API to exact match project by name
|
||||
projects, err := a.getProjects(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pro := range projects {
|
||||
if pro.Name == name {
|
||||
|
@ -72,7 +72,34 @@ func TestInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListNamespaces(t *testing.T) {
|
||||
// TODO
|
||||
// project exists
|
||||
server := test.NewServer(&test.RequestHandlerMapping{
|
||||
Method: http.MethodGet,
|
||||
Pattern: "/api/projects",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
data := `[{
|
||||
"name": "library",
|
||||
"metadata": {"public":true}
|
||||
},{
|
||||
"name": "library1",
|
||||
"metadata": {"public":true}
|
||||
}]`
|
||||
w.Write([]byte(data))
|
||||
},
|
||||
})
|
||||
defer server.Close()
|
||||
registry := &model.Registry{
|
||||
URL: server.URL,
|
||||
}
|
||||
adapter := newAdapter(registry)
|
||||
npQuery := &model.NamespaceQuery{
|
||||
Name: "lib",
|
||||
}
|
||||
namespace, err := adapter.ListNamespaces(npQuery)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(namespace))
|
||||
assert.Equal(t, "library", namespace[0].Name)
|
||||
assert.True(t, namespace[0].Metadata["public"].(bool))
|
||||
}
|
||||
|
||||
func TestPrepareForPush(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user