mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-22 16:48:30 +01:00
Merge pull request #11360 from ninjadq/rever_chart_api_change
Rever chart api change
This commit is contained in:
commit
b1284da96b
@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
commonhttp "github.com/goharbor/harbor/src/common/http"
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
"github.com/goharbor/harbor/src/replication"
|
||||
@ -70,7 +69,7 @@ func (c *Controller) DeleteChartVersion(namespace, chartName, version string) er
|
||||
return errors.New("invalid chart for deleting")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/api/%s/chartrepo/%s/charts/%s/%s", api.APIVersion, namespace, chartName, version)
|
||||
url := fmt.Sprintf("/api/chartrepo/%s/charts/%s/%s", namespace, chartName, version)
|
||||
req, _ := http.NewRequest(http.MethodDelete, url, nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
htesting "github.com/goharbor/harbor/src/testing"
|
||||
helm_repo "k8s.io/helm/pkg/repo"
|
||||
)
|
||||
@ -37,7 +36,7 @@ func TestStartMockServers(t *testing.T) {
|
||||
|
||||
// Test /health
|
||||
func TestGetHealthOfBaseHandler(t *testing.T) {
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s/api/%s/chartrepo/health", frontServer.URL, api.APIVersion))
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s/api/chartrepo/health", frontServer.URL))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/controller/event/metadata"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -16,9 +15,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/goharbor/harbor/src/common"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
commonhttp "github.com/goharbor/harbor/src/common/http"
|
||||
hlog "github.com/goharbor/harbor/src/common/utils/log"
|
||||
"github.com/goharbor/harbor/src/controller/event/metadata"
|
||||
n_event "github.com/goharbor/harbor/src/pkg/notifier/event"
|
||||
"github.com/goharbor/harbor/src/replication"
|
||||
rep_event "github.com/goharbor/harbor/src/replication/event"
|
||||
@ -27,15 +26,11 @@ import (
|
||||
const (
|
||||
agentHarbor = "HARBOR"
|
||||
contentLengthHeader = "Content-Length"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultRepo = "library"
|
||||
|
||||
chartRepoAPIPrefix = fmt.Sprintf("/api/%s/chartrepo", api.APIVersion)
|
||||
rootUploadingEndpoint = fmt.Sprintf("/api/%s/chartrepo/charts", api.APIVersion)
|
||||
chartRepoHealthEndpoint = fmt.Sprintf("/api/%s/chartrepo/health", api.APIVersion)
|
||||
chartRepoPrefix = "/chartrepo"
|
||||
defaultRepo = "library"
|
||||
rootUploadingEndpoint = "/api/chartrepo/charts"
|
||||
rootIndexEndpoint = "/chartrepo/index.yaml"
|
||||
chartRepoHealthEndpoint = "/api/chartrepo/health"
|
||||
)
|
||||
|
||||
// ProxyEngine is used to proxy the related traffics
|
||||
@ -229,19 +224,19 @@ func rewriteURLPath(req *http.Request) {
|
||||
|
||||
// Root uploading endpoint
|
||||
if incomingURLPath == rootUploadingEndpoint {
|
||||
req.URL.Path = strings.Replace(incomingURLPath, fmt.Sprintf("%s/chartrepo", api.APIVersion), defaultRepo, 1)
|
||||
req.URL.Path = strings.Replace(incomingURLPath, "chartrepo", defaultRepo, 1)
|
||||
return
|
||||
}
|
||||
|
||||
// Repository endpoints
|
||||
if strings.HasPrefix(incomingURLPath, chartRepoPrefix) {
|
||||
if strings.HasPrefix(incomingURLPath, "/chartrepo") {
|
||||
req.URL.Path = strings.TrimPrefix(incomingURLPath, "/chartrepo")
|
||||
return
|
||||
}
|
||||
|
||||
// API endpoints
|
||||
if strings.HasPrefix(incomingURLPath, chartRepoAPIPrefix) {
|
||||
req.URL.Path = strings.Replace(incomingURLPath, fmt.Sprintf("/%s/chartrepo", api.APIVersion), "", 1)
|
||||
if strings.HasPrefix(incomingURLPath, "/api/chartrepo") {
|
||||
req.URL.Path = strings.Replace(incomingURLPath, "/chartrepo", "", 1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,13 @@
|
||||
package chartserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
)
|
||||
|
||||
// Test the URL rewrite function
|
||||
func TestURLRewrite(t *testing.T) {
|
||||
req, err := createRequest(http.MethodGet, fmt.Sprintf("/api/%s/chartrepo/health", api.APIVersion))
|
||||
req, err := createRequest(http.MethodGet, "/api/chartrepo/health")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -19,7 +16,7 @@ func TestURLRewrite(t *testing.T) {
|
||||
t.Fatalf("Expect url format %s but got %s", "/health", req.URL.Path)
|
||||
}
|
||||
|
||||
req, err = createRequest(http.MethodGet, fmt.Sprintf("/api/%s/chartrepo/library/charts", api.APIVersion))
|
||||
req, err = createRequest(http.MethodGet, "/api/chartrepo/library/charts")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -28,7 +25,7 @@ func TestURLRewrite(t *testing.T) {
|
||||
t.Fatalf("Expect url format %s but got %s", "/api/library/charts", req.URL.Path)
|
||||
}
|
||||
|
||||
req, err = createRequest(http.MethodPost, fmt.Sprintf("/api/%s/chartrepo/charts", api.APIVersion))
|
||||
req, err = createRequest(http.MethodPost, "/api/chartrepo/charts")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/controller/event/metadata"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
@ -17,9 +16,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/goharbor/harbor/src/controller/event/metadata"
|
||||
|
||||
"github.com/goharbor/harbor/src/chartserver"
|
||||
"github.com/goharbor/harbor/src/common"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
"github.com/goharbor/harbor/src/common/rbac"
|
||||
hlog "github.com/goharbor/harbor/src/common/utils/log"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
@ -33,9 +33,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
namespaceParam = ":repo"
|
||||
nameParam = ":name"
|
||||
filenameParam = ":filename"
|
||||
namespaceParam = ":repo"
|
||||
nameParam = ":name"
|
||||
filenameParam = ":filename"
|
||||
defaultRepo = "library"
|
||||
rootUploadingEndpoint = "/api/chartrepo/charts"
|
||||
rootIndexEndpoint = "/chartrepo/index.yaml"
|
||||
chartRepoHealthEndpoint = "/api/chartrepo/health"
|
||||
|
||||
accessLevelPublic = iota
|
||||
accessLevelRead
|
||||
@ -51,13 +55,6 @@ const (
|
||||
chartPackageFileExtension = "tgz"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultRepo = "library"
|
||||
rootUploadingEndpoint = fmt.Sprintf("/api/%s/chartrepo/charts", api.APIVersion)
|
||||
chartRepoHealthEndpoint = fmt.Sprintf("/api/%s/chartrepo/health", api.APIVersion)
|
||||
rootIndexEndpoint = "/chartrepo/index.yaml"
|
||||
)
|
||||
|
||||
// chartController is a singleton instance
|
||||
var chartController *chartserver.Controller
|
||||
|
||||
@ -116,7 +113,7 @@ func (cra *ChartRepositoryAPI) requireAccess(action rbac.Action, subresource ...
|
||||
return cra.RequireProjectAccess(cra.namespace, action, subresource...)
|
||||
}
|
||||
|
||||
// GetHealthStatus handles GET /chartrepo/health
|
||||
// GetHealthStatus handles GET /api/chartrepo/health
|
||||
func (cra *ChartRepositoryAPI) GetHealthStatus() {
|
||||
// Check access
|
||||
if !cra.SecurityCtx.IsAuthenticated() {
|
||||
@ -606,7 +603,7 @@ func initializeChartController() (*chartserver.Controller, error) {
|
||||
return nil, errors.New("Endpoint URL of chart storage server is malformed")
|
||||
}
|
||||
|
||||
chartVersionURL := fmt.Sprintf(`^/api/%s/chartrepo/(?P<namespace>[^?#]+)/charts/(?P<name>[^?#]+)/(?P<version>[^?#]+)/?$`, api.APIVersion)
|
||||
chartVersionURL := fmt.Sprintf(`^/api/chartrepo/(?P<namespace>[^?#]+)/charts/(?P<name>[^?#]+)/(?P<version>[^?#]+)/?$`)
|
||||
skipper := middleware.NegativeSkipper(middleware.MethodAndPathSkipper(http.MethodDelete, regexp.MustCompile(chartVersionURL)))
|
||||
|
||||
controller, err := chartserver.NewController(url, orm.Middleware(), quota.UploadChartVersionMiddleware(), quota.RefreshForProjectMiddleware(skipper))
|
||||
|
@ -2,13 +2,11 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/goharbor/harbor/src/chartserver"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
"github.com/goharbor/harbor/src/core/promgr/metamgr"
|
||||
)
|
||||
@ -19,7 +17,7 @@ var (
|
||||
)
|
||||
|
||||
func TestIsMultipartFormData(t *testing.T) {
|
||||
req, err := createRequest(http.MethodPost, fmt.Sprintf("/api/%s/chartrepo/charts", api.APIVersion))
|
||||
req, err := createRequest(http.MethodPost, "/api/chartrepo/charts")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -57,7 +55,7 @@ func TestPrepareEnv(t *testing.T) {
|
||||
func TestGetHealthStatus(t *testing.T) {
|
||||
status := make(map[string]interface{})
|
||||
err := handleAndParse(&testingRequest{
|
||||
url: fmt.Sprintf("/api/%s/chartrepo/health", api.APIVersion),
|
||||
url: "/api/chartrepo/health",
|
||||
method: http.MethodGet,
|
||||
credential: sysAdmin,
|
||||
}, &status)
|
||||
@ -111,7 +109,7 @@ func TestDownloadChart(t *testing.T) {
|
||||
func TesListCharts(t *testing.T) {
|
||||
charts := make([]*chartserver.ChartInfo, 0)
|
||||
err := handleAndParse(&testingRequest{
|
||||
url: fmt.Sprintf("/api/%s/chartrepo/library/charts", api.APIVersion),
|
||||
url: "/api/chartrepo/library/charts",
|
||||
method: http.MethodGet,
|
||||
credential: projAdmin,
|
||||
}, &charts)
|
||||
@ -129,7 +127,7 @@ func TesListCharts(t *testing.T) {
|
||||
func TestListChartVersions(t *testing.T) {
|
||||
chartVersions := make(chartserver.ChartVersions, 0)
|
||||
err := handleAndParse(&testingRequest{
|
||||
url: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor", api.APIVersion),
|
||||
url: "/api/chartrepo/library/charts/harbor",
|
||||
method: http.MethodGet,
|
||||
credential: projAdmin,
|
||||
}, &chartVersions)
|
||||
@ -147,7 +145,7 @@ func TestListChartVersions(t *testing.T) {
|
||||
func TestGetChartVersion(t *testing.T) {
|
||||
chartV := &chartserver.ChartVersionDetails{}
|
||||
err := handleAndParse(&testingRequest{
|
||||
url: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor/0.2.0", api.APIVersion),
|
||||
url: "/api/chartrepo/library/charts/harbor/0.2.0",
|
||||
method: http.MethodGet,
|
||||
credential: projAdmin,
|
||||
}, chartV)
|
||||
@ -169,7 +167,7 @@ func TestGetChartVersion(t *testing.T) {
|
||||
func TestDeleteChartVersion(t *testing.T) {
|
||||
runCodeCheckingCases(t, &codeCheckingCase{
|
||||
request: &testingRequest{
|
||||
url: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor/0.2.1", api.APIVersion),
|
||||
url: "/api/chartrepo/library/charts/harbor/0.2.1",
|
||||
method: http.MethodDelete,
|
||||
credential: projAdmin,
|
||||
},
|
||||
@ -181,7 +179,7 @@ func TestDeleteChartVersion(t *testing.T) {
|
||||
func TestDeleteChart(t *testing.T) {
|
||||
runCodeCheckingCases(t, &codeCheckingCase{
|
||||
request: &testingRequest{
|
||||
url: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor", api.APIVersion),
|
||||
url: "/api/chartrepo/library/charts/harbor",
|
||||
method: http.MethodDelete,
|
||||
credential: projAdmin,
|
||||
},
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/server/middleware/security"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -29,6 +28,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/goharbor/harbor/src/server/middleware/security"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/dghubble/sling"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
@ -166,15 +167,15 @@ func init() {
|
||||
beego.Router("/api/projects/:pid([0-9]+)/immutabletagrules/:id([0-9]+)", &ImmutableTagRuleAPI{})
|
||||
// Charts are controlled under projects
|
||||
chartRepositoryAPIType := &ChartRepositoryAPI{}
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/health", chartRepositoryAPIType, "get:GetHealthStatus")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/charts", chartRepositoryAPIType, "get:ListCharts")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "get:ListChartVersions")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "delete:DeleteChart")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "get:GetChartVersion")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "delete:DeleteChartVersion")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/:repo/prov", chartRepositoryAPIType, "post:UploadChartProvFile")
|
||||
beego.Router("/api/"+api.APIVersion+"/chartrepo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
beego.Router("/api/chartrepo/health", chartRepositoryAPIType, "get:GetHealthStatus")
|
||||
beego.Router("/api/chartrepo/:repo/charts", chartRepositoryAPIType, "get:ListCharts")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "get:ListChartVersions")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "delete:DeleteChart")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "get:GetChartVersion")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "delete:DeleteChartVersion")
|
||||
beego.Router("/api/chartrepo/:repo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
beego.Router("/api/chartrepo/:repo/prov", chartRepositoryAPIType, "post:UploadChartProvFile")
|
||||
beego.Router("/api/chartrepo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
|
||||
// Repository services
|
||||
beego.Router("/chartrepo/:repo/index.yaml", chartRepositoryAPIType, "get:GetIndexByRepo")
|
||||
|
@ -18,11 +18,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goharbor/harbor/src/chartserver"
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
)
|
||||
|
||||
func (c *client) ListAllCharts(project, repository string) ([]*chartserver.ChartVersion, error) {
|
||||
url := c.buildURL(fmt.Sprintf("/api/%s/chartrepo/%s/charts/%s", api.APIVersion, project, repository))
|
||||
url := c.buildURL(fmt.Sprintf("/api/chartrepo/%s/charts/%s", project, repository))
|
||||
var charts []*chartserver.ChartVersion
|
||||
if err := c.httpclient.Get(url, &charts); err != nil {
|
||||
return nil, err
|
||||
@ -31,11 +30,11 @@ func (c *client) ListAllCharts(project, repository string) ([]*chartserver.Chart
|
||||
}
|
||||
|
||||
func (c *client) DeleteChart(project, repository, version string) error {
|
||||
url := c.buildURL(fmt.Sprintf("/api/%s/chartrepo/%s/charts/%s/%s", api.APIVersion, project, repository, version))
|
||||
url := c.buildURL(fmt.Sprintf("/api/chartrepo/%s/charts/%s/%s", project, repository, version))
|
||||
return c.httpclient.Delete(url)
|
||||
}
|
||||
|
||||
func (c *client) DeleteChartRepository(project, repository string) error {
|
||||
url := c.buildURL(fmt.Sprintf("/api/%s/chartrepo/%s/charts/%s", api.APIVersion, project, repository))
|
||||
url := c.buildURL(fmt.Sprintf("/api/chartrepo/%s/charts/%s", project, repository))
|
||||
return c.httpclient.Delete(url)
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ import { ListChartVersionRoComponent } from "./list-chart-version-ro/list-chart-
|
||||
import { IServiceConfig, SERVICE_CONFIG } from "../../lib/entities/service.config";
|
||||
import { ErrorHandler } from "../../lib/utils/error-handler";
|
||||
import { HarborLibraryModule } from "../../lib/harbor-library.module";
|
||||
import { CURRENT_BASE_HREF } from "../../lib/utils/utils";
|
||||
import { CURRENT_BASE_HREF, V1_BASE_HREF } from "../../lib/utils/utils";
|
||||
|
||||
const uiLibConfig: IServiceConfig = {
|
||||
enablei18Support: true,
|
||||
@ -67,8 +67,9 @@ const uiLibConfig: IServiceConfig = {
|
||||
configurationEndpoint: CURRENT_BASE_HREF + "/configurations",
|
||||
scanJobEndpoint: CURRENT_BASE_HREF + "/jobs/scan",
|
||||
labelEndpoint: CURRENT_BASE_HREF + "/labels",
|
||||
helmChartEndpoint: CURRENT_BASE_HREF + "/chartrepo",
|
||||
helmChartEndpoint: V1_BASE_HREF + "/chartrepo",
|
||||
downloadChartEndpoint: "/chartrepo",
|
||||
helmChartLabelEndpoint: CURRENT_BASE_HREF + "/chartrepo",
|
||||
gcEndpoint: CURRENT_BASE_HREF + "/system/gc",
|
||||
ScanAllEndpoint: CURRENT_BASE_HREF + "/system/scanAll",
|
||||
quotaUrl: CURRENT_BASE_HREF + "/quotas"
|
||||
|
@ -229,6 +229,8 @@ export interface IServiceConfig {
|
||||
*/
|
||||
downloadChartEndpoint?: string;
|
||||
|
||||
helmChartLabelEndpoint?: string;
|
||||
|
||||
gcEndpoint?: string;
|
||||
|
||||
ScanAllEndpoint?: string;
|
||||
|
@ -34,7 +34,7 @@ import {
|
||||
ErrorHandler,
|
||||
DefaultErrorHandler
|
||||
} from './utils/error-handler';
|
||||
import { DEFAULT_LANG_COOKIE_KEY, DEFAULT_SUPPORTING_LANGS, DEFAULT_LANG, CURRENT_BASE_HREF } from './utils/utils';
|
||||
import { DEFAULT_LANG_COOKIE_KEY, DEFAULT_SUPPORTING_LANGS, DEFAULT_LANG, CURRENT_BASE_HREF, V1_BASE_HREF } from './utils/utils';
|
||||
import { OperationService } from './components/operation/operation.service';
|
||||
import { GcHistoryComponent } from "./components/config/gc/gc-history/gc-history.component";
|
||||
import { GcComponent } from "./components/config/gc/gc.component";
|
||||
@ -97,7 +97,8 @@ export const DefaultServiceConfig: IServiceConfig = {
|
||||
configurationEndpoint: CURRENT_BASE_HREF + "/configurations",
|
||||
scanJobEndpoint: CURRENT_BASE_HREF + "/jobs/scan",
|
||||
labelEndpoint: CURRENT_BASE_HREF + "/labels",
|
||||
helmChartEndpoint: CURRENT_BASE_HREF + "/chartrepo",
|
||||
helmChartEndpoint: V1_BASE_HREF + "/chartrepo",
|
||||
helmChartLabelEndpoint: CURRENT_BASE_HREF + "/chartrepo",
|
||||
downloadChartEndpoint: "/chartrepo",
|
||||
gcEndpoint: CURRENT_BASE_HREF + "/system/gc",
|
||||
ScanAllEndpoint: CURRENT_BASE_HREF + "/system/scanAll"
|
||||
|
@ -6,7 +6,7 @@ import { RequestQueryParams } from "./RequestQueryParams";
|
||||
import { Label } from "./interface";
|
||||
|
||||
import { IServiceConfig, SERVICE_CONFIG } from "../entities/service.config";
|
||||
import { buildHttpRequestOptions, CURRENT_BASE_HREF, HTTP_JSON_OPTIONS } from "../utils/utils";
|
||||
import { buildHttpRequestOptions, CURRENT_BASE_HREF, V1_BASE_HREF, HTTP_JSON_OPTIONS } from "../utils/utils";
|
||||
import { Observable, throwError as observableThrowError } from "rxjs";
|
||||
|
||||
export abstract class LabelService {
|
||||
@ -72,6 +72,7 @@ export abstract class LabelService {
|
||||
export class LabelDefaultService extends LabelService {
|
||||
labelUrl: string;
|
||||
chartUrl: string;
|
||||
chartLabelUrl: string;
|
||||
|
||||
constructor(
|
||||
@Inject(SERVICE_CONFIG) config: IServiceConfig,
|
||||
@ -79,7 +80,8 @@ export class LabelDefaultService extends LabelService {
|
||||
) {
|
||||
super();
|
||||
this.labelUrl = config.labelEndpoint ? config.labelEndpoint : CURRENT_BASE_HREF + "/labels";
|
||||
this.chartUrl = config.helmChartEndpoint ? config.helmChartEndpoint : CURRENT_BASE_HREF + "/chartrepo";
|
||||
this.chartUrl = config.helmChartEndpoint ? config.helmChartEndpoint : V1_BASE_HREF + "/chartrepo";
|
||||
this.chartLabelUrl = config.helmChartLabelEndpoint ? config.helmChartLabelEndpoint : CURRENT_BASE_HREF + "/chartrepo";
|
||||
}
|
||||
|
||||
|
||||
@ -208,7 +210,7 @@ export class LabelDefaultService extends LabelService {
|
||||
chartName: string,
|
||||
version: string
|
||||
): Observable<Label[]> {
|
||||
return this.http.get<Label[]>(`${this.chartUrl}/${projectName}/charts/${chartName}/${version}/labels`);
|
||||
return this.http.get<Label[]>(`${this.chartLabelUrl}/${projectName}/charts/${chartName}/${version}/labels`);
|
||||
}
|
||||
|
||||
markChartLabel(
|
||||
@ -217,7 +219,7 @@ export class LabelDefaultService extends LabelService {
|
||||
version: string,
|
||||
label: Label,
|
||||
): Observable<any> {
|
||||
return this.http.post(`${this.chartUrl}/${projectName}/charts/${chartName}/${version}/labels`,
|
||||
return this.http.post(`${this.chartLabelUrl}/${projectName}/charts/${chartName}/${version}/labels`,
|
||||
JSON.stringify(label), HTTP_JSON_OPTIONS);
|
||||
}
|
||||
|
||||
@ -227,7 +229,7 @@ export class LabelDefaultService extends LabelService {
|
||||
version: string,
|
||||
label: Label,
|
||||
): Observable<any> {
|
||||
return this.http.delete(`${this.chartUrl}/${projectName}/charts/${chartName}/${version}/labels/${label.id}`, HTTP_JSON_OPTIONS);
|
||||
return this.http.delete(`${this.chartLabelUrl}/${projectName}/charts/${chartName}/${version}/labels/${label.id}`, HTTP_JSON_OPTIONS);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,12 @@ enum APILevels {
|
||||
V1 = '',
|
||||
V2 = '/v2.0'
|
||||
}
|
||||
|
||||
/**
|
||||
* v1 base href
|
||||
*/
|
||||
export const V1_BASE_HREF = '/api' + APILevels.V1;
|
||||
|
||||
/**
|
||||
* Current base href
|
||||
*/
|
||||
|
@ -17,14 +17,14 @@ package harbor
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/replication/filter"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
"github.com/goharbor/harbor/src/replication/filter"
|
||||
|
||||
common_http "github.com/goharbor/harbor/src/common/http"
|
||||
"github.com/goharbor/harbor/src/replication/model"
|
||||
)
|
||||
@ -54,7 +54,7 @@ func (a *adapter) FetchCharts(filters []*model.Filter) ([]*model.Resource, error
|
||||
|
||||
resources := []*model.Resource{}
|
||||
for _, project := range projects {
|
||||
url := fmt.Sprintf("%s/api/%s/chartrepo/%s/charts", a.getURL(), api.APIVersion, project.Name)
|
||||
url := fmt.Sprintf("%s/api/chartrepo/%s/charts", a.getURL(), project.Name)
|
||||
repositories := []*model.Repository{}
|
||||
if err := a.client.Get(url, &repositories); err != nil {
|
||||
return nil, err
|
||||
@ -72,7 +72,7 @@ func (a *adapter) FetchCharts(filters []*model.Filter) ([]*model.Resource, error
|
||||
|
||||
for _, repository := range repositories {
|
||||
name := strings.SplitN(repository.Name, "/", 2)[1]
|
||||
url := fmt.Sprintf("%s/api/%s/chartrepo/%s/charts/%s", a.getURL(), api.APIVersion, project.Name, name)
|
||||
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s", a.getURL(), project.Name, name)
|
||||
versions := []*chartVersion{}
|
||||
if err := a.client.Get(url, &versions); err != nil {
|
||||
return nil, err
|
||||
@ -133,7 +133,7 @@ func (a *adapter) getChartInfo(name, version string) (*chartVersionDetail, error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
url := fmt.Sprintf("%s/api/%s/chartrepo/%s/charts/%s/%s", a.url, api.APIVersion, project, name, version)
|
||||
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s/%s", a.url, project, name, version)
|
||||
info := &chartVersionDetail{}
|
||||
if err = a.client.Get(url, info); err != nil {
|
||||
return nil, err
|
||||
@ -193,7 +193,7 @@ func (a *adapter) UploadChart(name, version string, chart io.Reader) error {
|
||||
}
|
||||
w.Close()
|
||||
|
||||
url := fmt.Sprintf("%s/api/%s/chartrepo/%s/charts", a.url, api.APIVersion, project)
|
||||
url := fmt.Sprintf("%s/api/chartrepo/%s/charts", a.url, project)
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, url, buf)
|
||||
if err != nil {
|
||||
@ -224,7 +224,7 @@ func (a *adapter) DeleteChart(name, version string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf("%s/api/%s/chartrepo/%s/charts/%s/%s", a.url, api.APIVersion, project, name, version)
|
||||
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s/%s", a.url, project, name, version)
|
||||
return a.client.Delete(url)
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ func TestFetchCharts(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Pattern: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor", api.APIVersion),
|
||||
Pattern: "/api/chartrepo/library/charts/harbor",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
data := `[{
|
||||
"name": "harbor",
|
||||
@ -56,7 +56,7 @@ func TestFetchCharts(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Pattern: fmt.Sprintf("/api/%s/chartrepo/library/charts", api.APIVersion),
|
||||
Pattern: "/api/chartrepo/library/charts",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
data := `[{
|
||||
"name": "harbor"
|
||||
@ -102,7 +102,7 @@ func TestFetchCharts(t *testing.T) {
|
||||
func TestChartExist(t *testing.T) {
|
||||
server := test.NewServer(&test.RequestHandlerMapping{
|
||||
Method: http.MethodGet,
|
||||
Pattern: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor/1.0", api.APIVersion),
|
||||
Pattern: "/api/chartrepo/library/charts/harbor/1.0",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
data := `{
|
||||
"metadata": {
|
||||
@ -127,7 +127,7 @@ func TestDownloadChart(t *testing.T) {
|
||||
server := test.NewServer([]*test.RequestHandlerMapping{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Pattern: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor/1.0", api.APIVersion),
|
||||
Pattern: "/api/chartrepo/library/charts/harbor/1.0",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
data := `{
|
||||
"metadata": {
|
||||
@ -158,7 +158,7 @@ func TestDownloadChart(t *testing.T) {
|
||||
func TestUploadChart(t *testing.T) {
|
||||
server := test.NewServer(&test.RequestHandlerMapping{
|
||||
Method: http.MethodPost,
|
||||
Pattern: fmt.Sprintf("/api/%s/chartrepo/library/charts", api.APIVersion),
|
||||
Pattern: "/api/chartrepo/library/charts",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
},
|
||||
@ -176,7 +176,7 @@ func TestUploadChart(t *testing.T) {
|
||||
func TestDeleteChart(t *testing.T) {
|
||||
server := test.NewServer(&test.RequestHandlerMapping{
|
||||
Method: http.MethodDelete,
|
||||
Pattern: fmt.Sprintf("/api/%s/chartrepo/library/charts/harbor/1.0", api.APIVersion),
|
||||
Pattern: "/api/chartrepo/library/charts/harbor/1.0",
|
||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
},
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/goharbor/harbor/src/common/api"
|
||||
"github.com/goharbor/harbor/src/lib"
|
||||
"github.com/goharbor/harbor/src/pkg/types"
|
||||
"github.com/goharbor/harbor/src/server/middleware"
|
||||
@ -30,7 +29,7 @@ import (
|
||||
|
||||
// UploadChartVersionMiddleware middleware to request count resources for the project
|
||||
func UploadChartVersionMiddleware() func(http.Handler) http.Handler {
|
||||
chartsURL := fmt.Sprintf(`^/api/%s/chartrepo/(?P<namespace>[^?#]+)/charts/?$`, api.APIVersion)
|
||||
chartsURL := `^/api/chartrepo/(?P<namespace>[^?#]+)/charts/?$`
|
||||
skipper := middleware.NegativeSkipper(middleware.MethodAndPathSkipper(http.MethodPost, regexp.MustCompile(chartsURL)))
|
||||
|
||||
return RequestMiddleware(RequestConfig{
|
||||
|
@ -58,6 +58,7 @@ func Test_projectReferenceObject(t *testing.T) {
|
||||
{"/api/v2.0/projects/library/repositories", args{req("/api/v2.0/projects/library/repositories")}, "project", "1", false},
|
||||
{"/api/v2.0/projects/demo", args{req("/api/v2.0/projects/demo")}, "", "", true},
|
||||
{"/api/v2.0/library", args{req("/api/v2.0/library")}, "", "", true},
|
||||
{"/api/chartrepo/library/charts", args{req("/api/chartrepo/library/charts")}, "project", "1", false},
|
||||
{"/v2/library/photon/manifests/2.0", args{req("/v2/library/photon/manifests/2.0")}, "project", "1", false},
|
||||
{"/v2", args{req("/v2")}, "", "", true},
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ func (o *oidcCli) Generate(req *http.Request) security.Context {
|
||||
if path != "/service/token" &&
|
||||
!strings.HasPrefix(path, "/v2") &&
|
||||
!strings.HasPrefix(path, "/chartrepo/") &&
|
||||
!strings.HasPrefix(path, "/api/chartrepo/") &&
|
||||
!strings.HasPrefix(path, fmt.Sprintf("/api/%s/chartrepo/", api.APIVersion)) {
|
||||
return nil
|
||||
}
|
||||
|
@ -31,8 +31,9 @@ func ParseProjectName(r *http.Request) string {
|
||||
var projectName string
|
||||
|
||||
prefixes := []string{
|
||||
fmt.Sprintf("/api/%s/projects/", api.APIVersion), // v2.0 management APIs
|
||||
fmt.Sprintf("/api/%s/chartrepo/", api.APIVersion), // chartmuseum APIs
|
||||
fmt.Sprintf("/api/%s/projects/", api.APIVersion), // v2.0 management APIs
|
||||
"/api/chartrepo/", // chartmuseum APIs
|
||||
fmt.Sprintf("/api/%s/chartrepo/", api.APIVersion), // chartmuseum Label APIs
|
||||
}
|
||||
|
||||
for _, prefix := range prefixes {
|
||||
|
@ -56,6 +56,15 @@ func registerRoutes() {
|
||||
beego.Router("/chartrepo/:repo/index.yaml", chartRepositoryAPIType, "get:GetIndexByRepo")
|
||||
beego.Router("/chartrepo/index.yaml", chartRepositoryAPIType, "get:GetIndex")
|
||||
beego.Router("/chartrepo/:repo/charts/:filename", chartRepositoryAPIType, "get:DownloadChart")
|
||||
beego.Router("/api/chartrepo/health", chartRepositoryAPIType, "get:GetHealthStatus")
|
||||
beego.Router("/api/chartrepo/:repo/charts", chartRepositoryAPIType, "get:ListCharts")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "get:ListChartVersions")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "delete:DeleteChart")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "get:GetChartVersion")
|
||||
beego.Router("/api/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "delete:DeleteChartVersion")
|
||||
beego.Router("/api/chartrepo/:repo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
beego.Router("/api/chartrepo/:repo/prov", chartRepositoryAPIType, "post:UploadChartProvFile")
|
||||
beego.Router("/api/chartrepo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
}
|
||||
|
||||
// Error pages
|
||||
|
@ -110,18 +110,6 @@ func registerLegacyRoutes() {
|
||||
|
||||
// APIs for chart repository
|
||||
if config.WithChartMuseum() {
|
||||
// Charts are controlled under projects
|
||||
chartRepositoryAPIType := &api.ChartRepositoryAPI{}
|
||||
beego.Router("/api/"+version+"/chartrepo/health", chartRepositoryAPIType, "get:GetHealthStatus")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts", chartRepositoryAPIType, "get:ListCharts")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "get:ListChartVersions")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "delete:DeleteChart")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "get:GetChartVersion")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "delete:DeleteChartVersion")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/prov", chartRepositoryAPIType, "post:UploadChartProvFile")
|
||||
beego.Router("/api/"+version+"/chartrepo/charts", chartRepositoryAPIType, "post:UploadChartVersion")
|
||||
|
||||
// Labels for chart
|
||||
chartLabelAPIType := &api.ChartLabelAPI{}
|
||||
beego.Router("/api/"+version+"/chartrepo/:repo/charts/:name/:version/labels", chartLabelAPIType, "get:GetLabels;post:MarkLabel")
|
||||
|
@ -2,7 +2,7 @@ from __future__ import absolute_import
|
||||
|
||||
import unittest
|
||||
|
||||
from testutils import ADMIN_CLIENT
|
||||
from testutils import ADMIN_CLIENT, CHART_API_CLIENT
|
||||
from testutils import TEARDOWN
|
||||
from library.user import User
|
||||
from library.project import Project
|
||||
@ -27,7 +27,7 @@ class TestProjects(unittest.TestCase):
|
||||
@unittest.skipIf(TEARDOWN == False, "Test data won't be erased.")
|
||||
def test_ClearData(self):
|
||||
#1. Delete chart file;
|
||||
self.chart.delete_chart_with_version(TestProjects.project_chart_name, TestProjects.CHART_NAME, TestProjects.VERSION, **ADMIN_CLIENT)
|
||||
self.chart.delete_chart_with_version(TestProjects.project_chart_name, TestProjects.CHART_NAME, TestProjects.VERSION, **CHART_API_CLIENT)
|
||||
|
||||
#2. Delete project(PA);
|
||||
self.project.delete_project(TestProjects.project_chart_id, **TestProjects.USER_CHART_CLIENT)
|
||||
@ -50,8 +50,8 @@ class TestProjects(unittest.TestCase):
|
||||
3. Delete user(UA).
|
||||
"""
|
||||
url = ADMIN_CLIENT["endpoint"]
|
||||
|
||||
user_chart_password = "Aa123456"
|
||||
chart_api_url = CHART_API_CLIENT['endpoint']
|
||||
user_chart_password = 'Aa123456'
|
||||
TestProjects.CHART_NAME = 'mariadb'
|
||||
TestProjects.VERSION = '4.3.1'
|
||||
|
||||
@ -60,14 +60,16 @@ class TestProjects(unittest.TestCase):
|
||||
|
||||
TestProjects.USER_CHART_CLIENT=dict(endpoint = url, username = user_chart_name, password = user_chart_password)
|
||||
|
||||
TestProjects.API_CHART_CLIENT=dict(endpoint = chart_api_url, username = user_chart_name, password = user_chart_password)
|
||||
|
||||
#2. Create a new project(PA) by user(UA);
|
||||
TestProjects.project_chart_id, TestProjects.project_chart_name = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_CHART_CLIENT)
|
||||
|
||||
#3. Upload a chart file to project(PA);
|
||||
self.chart.upload_chart(TestProjects.project_chart_name, r'./tests/apitests/python/mariadb-{}.tgz'.format(TestProjects.VERSION), **TestProjects.USER_CHART_CLIENT)
|
||||
self.chart.upload_chart(TestProjects.project_chart_name, r'./tests/apitests/python/mariadb-{}.tgz'.format(TestProjects.VERSION), **TestProjects.API_CHART_CLIENT)
|
||||
|
||||
#4. Chart file should be exist in project(PA).
|
||||
self.chart.chart_should_exist(TestProjects.project_chart_name, TestProjects.CHART_NAME, **TestProjects.USER_CHART_CLIENT)
|
||||
self.chart.chart_should_exist(TestProjects.project_chart_name, TestProjects.CHART_NAME, **TestProjects.API_CHART_CLIENT)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -14,6 +14,7 @@ admin_pwd = "Harbor12345"
|
||||
harbor_server = os.environ["HARBOR_HOST"]
|
||||
#CLIENT=dict(endpoint="https://"+harbor_server+"/api")
|
||||
ADMIN_CLIENT=dict(endpoint = os.environ.get("HARBOR_HOST_SCHEMA", "https")+ "://"+harbor_server+"/api/v2.0", username = admin_user, password = admin_pwd)
|
||||
CHART_API_CLIENT=dict(endpoint = os.environ.get("HARBOR_HOST_SCHEMA", "https")+ "://"+harbor_server+"/api", username = admin_user, password = admin_pwd)
|
||||
USER_ROLE=dict(admin=0,normal=1)
|
||||
TEARDOWN = os.environ.get('TEARDOWN', 'true').lower() in ('true', 'yes')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user