mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 12:15:20 +01:00
Add UT cases for the code of supporting chart repo server
add UT cases for cache add UT cases for ChartOperator add UT cases for the main API service of chart server export some consts in the security.go of filter package to let them visible in chartserver package
This commit is contained in:
parent
44cbb29664
commit
da4359f56b
374
src/chartserver/base_test.go
Normal file
374
src/chartserver/base_test.go
Normal file
File diff suppressed because one or more lines are too long
@ -160,7 +160,7 @@ func initCacheDriver(driverType string) (beego_cache.Cache, string) {
|
||||
break
|
||||
}
|
||||
|
||||
hlog.Info("Driver type %s is not suppotred, enable memory cache by default for chart caching")
|
||||
hlog.Infof("Failed to config cache with driver '%s', enable memory cache by default for chart cache instead", driverType)
|
||||
//Any other cases, use memory cache
|
||||
return beego_cache.NewMemoryCache(), cacheDriverMem
|
||||
}
|
||||
|
90
src/chartserver/cache_test.go
Normal file
90
src/chartserver/cache_test.go
Normal file
@ -0,0 +1,90 @@
|
||||
package chartserver
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
"k8s.io/helm/pkg/proto/hapi/chart"
|
||||
helm_repo "k8s.io/helm/pkg/repo"
|
||||
)
|
||||
|
||||
var (
|
||||
mockChart = &ChartVersionDetails{
|
||||
Metadata: &helm_repo.ChartVersion{
|
||||
Metadata: &chart.Metadata{
|
||||
Name: "mock_chart",
|
||||
Version: "0.1.0",
|
||||
},
|
||||
Digest: "mock_digest",
|
||||
},
|
||||
Dependencies: make([]*chartutil.Dependency, 0),
|
||||
}
|
||||
)
|
||||
|
||||
//Test the no cache set scenario
|
||||
func TestNoCache(t *testing.T) {
|
||||
chartCache := NewChartCache()
|
||||
if chartCache == nil {
|
||||
t.Fatalf("cache instance should not be nil")
|
||||
}
|
||||
|
||||
if chartCache.IsEnabled() {
|
||||
t.Fatal("chart cache should not be enabled")
|
||||
}
|
||||
}
|
||||
|
||||
//Test the in memory cache
|
||||
func TestInMemoryCache(t *testing.T) {
|
||||
os.Setenv(cacheDriverENVKey, cacheDriverMem)
|
||||
|
||||
chartCache := NewChartCache()
|
||||
if chartCache == nil {
|
||||
t.Fatalf("cache instance should not be nil")
|
||||
}
|
||||
|
||||
if !chartCache.IsEnabled() {
|
||||
t.Fatal("chart cache should be enabled")
|
||||
}
|
||||
|
||||
if chartCache.driverType != cacheDriverMem {
|
||||
t.Fatalf("expect driver type %s but got %s", cacheDriverMem, chartCache.driverType)
|
||||
}
|
||||
|
||||
chartCache.PutChart(mockChart)
|
||||
theCachedChart := chartCache.GetChart(mockChart.Metadata.Digest)
|
||||
if theCachedChart == nil || theCachedChart.Metadata.Name != mockChart.Metadata.Name {
|
||||
t.Fatal("In memory cache does work")
|
||||
}
|
||||
|
||||
os.Unsetenv(cacheDriverENVKey)
|
||||
}
|
||||
|
||||
//Test redis cache
|
||||
//Failed to config redis cache and then use in memory instead
|
||||
func TestRedisCache(t *testing.T) {
|
||||
os.Setenv(cacheDriverENVKey, cacheDriverRedis)
|
||||
os.Setenv(redisENVKey, ":6379")
|
||||
|
||||
chartCache := NewChartCache()
|
||||
if chartCache == nil {
|
||||
t.Fatalf("cache instance should not be nil")
|
||||
}
|
||||
|
||||
if !chartCache.IsEnabled() {
|
||||
t.Fatal("chart cache should be enabled")
|
||||
}
|
||||
|
||||
if chartCache.driverType != cacheDriverRedis {
|
||||
t.Fatalf("expect driver type '%s' but got '%s'", cacheDriverRedis, chartCache.driverType)
|
||||
}
|
||||
|
||||
chartCache.PutChart(mockChart)
|
||||
theCachedChart := chartCache.GetChart(mockChart.Metadata.Digest)
|
||||
if theCachedChart == nil || theCachedChart.Metadata.Name != mockChart.Metadata.Name {
|
||||
t.Fatal("In memory cache does work")
|
||||
}
|
||||
|
||||
os.Unsetenv(redisENVKey)
|
||||
os.Unsetenv(cacheDriverENVKey)
|
||||
}
|
49
src/chartserver/chart_operator_test.go
Normal file
49
src/chartserver/chart_operator_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package chartserver
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetChartDetails(t *testing.T) {
|
||||
chartOpr := ChartOperator{}
|
||||
chartDetails, err := chartOpr.GetChartDetails(helmChartContent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(chartDetails.Dependencies) == 0 {
|
||||
t.Fatal("At least 1 dependency exitsing, but we got 0 now")
|
||||
}
|
||||
|
||||
if len(chartDetails.Values) == 0 {
|
||||
t.Fatal("At least 1 value existing, but we got 0 now")
|
||||
}
|
||||
|
||||
if chartDetails.Values["adminserver.adminPassword"] != "Harbor12345" {
|
||||
t.Fatalf("The value of 'adminserver.adminPassword' should be 'Harbor12345' but we got '%s' now", chartDetails.Values["adminserver.adminPassword"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetChartList(t *testing.T) {
|
||||
chartOpr := ChartOperator{}
|
||||
infos, err := chartOpr.GetChartList(chartListContent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(infos) != 2 {
|
||||
t.Fatalf("Length of chart list should be 2, but we got %d now", len(infos))
|
||||
}
|
||||
|
||||
foundHarbor := false
|
||||
for _, chart := range infos {
|
||||
if chart.Name == "harbor" {
|
||||
foundHarbor = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !foundHarbor {
|
||||
t.Fatal("Expect chart named with 'harbor' but got nothing")
|
||||
}
|
||||
}
|
@ -53,15 +53,15 @@ func (cc *ChartClient) GetContent(url string) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("failed to retrieve content from url %s", url)
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("failed to retrieve content from url '%s' with error: %s", url, content)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
210
src/chartserver/controller_test.go
Normal file
210
src/chartserver/controller_test.go
Normal file
@ -0,0 +1,210 @@
|
||||
package chartserver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
helm_repo "k8s.io/helm/pkg/repo"
|
||||
)
|
||||
|
||||
//Prepare, start the mock servers
|
||||
func TestStartServers(t *testing.T) {
|
||||
if err := startMockServers(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
//Test /health
|
||||
func TestGetHealthOfBaseHandler(t *testing.T) {
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s/health", getTheAddrOfFrontServer()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
status := make(map[string]interface{})
|
||||
if err := json.Unmarshal(content, &status); err != nil {
|
||||
t.Fatalf("Unmarshal error: %s, %s", err, content)
|
||||
}
|
||||
healthy, ok := status["health"].(bool)
|
||||
if !ok || !healthy {
|
||||
t.Fatalf("Expect healthy of server to be 'true' but got %v", status["health"])
|
||||
}
|
||||
}
|
||||
|
||||
//Get /repo1/index.yaml
|
||||
func TestGetIndexYamlByRepo(t *testing.T) {
|
||||
indexFile, err := getIndexYaml("/repo1/index.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(indexFile.Entries) != 3 {
|
||||
t.Fatalf("Expect index file with 3 entries, but got %d", len(indexFile.Entries))
|
||||
}
|
||||
}
|
||||
|
||||
//Test get /index.yaml
|
||||
func TestGetUnifiedYamlFile(t *testing.T) {
|
||||
indexFile, err := getIndexYaml("/index.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(indexFile.Entries) != 5 {
|
||||
t.Fatalf("Expect index file with 5 entries, but got %d", len(indexFile.Entries))
|
||||
}
|
||||
|
||||
_, ok := indexFile.Entries["repo1/harbor"]
|
||||
if !ok {
|
||||
t.Fatal("Expect chart entry 'repo1/harbor' but got nothing")
|
||||
}
|
||||
|
||||
_, ok = indexFile.Entries["repo2/harbor"]
|
||||
if !ok {
|
||||
t.Fatal("Expect chart entry 'repo2/harbor' but got nothing")
|
||||
}
|
||||
}
|
||||
|
||||
//Test download /:repo/charts/chart.tar
|
||||
//Use this case to test the proxy function
|
||||
func TestDownloadChart(t *testing.T) {
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s/repo1/charts/harbor-0.2.0.tgz", getTheAddrOfFrontServer()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
gotSize := len(content)
|
||||
expectSize := len(helmChartContent)
|
||||
|
||||
if gotSize != expectSize {
|
||||
t.Fatalf("Expect %d bytes data but got %d bytes", expectSize, gotSize)
|
||||
}
|
||||
}
|
||||
|
||||
//Test get /api/:repo/charts
|
||||
func TestRetrieveChartList(t *testing.T) {
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s/api/repo1/charts", getTheAddrOfFrontServer()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
chartList := make([]*ChartInfo, 0)
|
||||
err = json.Unmarshal(content, &chartList)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal error: %s", err)
|
||||
}
|
||||
|
||||
if len(chartList) != 2 {
|
||||
t.Fatalf("Expect to get 2 charts in the list but got %d", len(chartList))
|
||||
}
|
||||
|
||||
foundItem := false
|
||||
for _, chartInfo := range chartList {
|
||||
if chartInfo.Name == "hello-helm" && chartInfo.TotalVersions == 2 {
|
||||
foundItem = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !foundItem {
|
||||
t.Fatalf("Expect chart 'hello-helm' with 2 versions but got nothing")
|
||||
}
|
||||
}
|
||||
|
||||
//Test get /api/:repo/charts/:chart_name/:version
|
||||
func TestGetChartVersion(t *testing.T) {
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s/api/repo1/charts/harbor/0.2.0", getTheAddrOfFrontServer()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
chartVersion := &ChartVersionDetails{}
|
||||
if err = json.Unmarshal(content, chartVersion); err != nil {
|
||||
t.Fatalf("Unmarshal error: %s", err)
|
||||
}
|
||||
|
||||
if chartVersion.Metadata.Name != "harbor" {
|
||||
t.Fatalf("Expect harbor chart version but got %s", chartVersion.Metadata.Name)
|
||||
}
|
||||
|
||||
if chartVersion.Metadata.Version != "0.2.0" {
|
||||
t.Fatalf("Expect version '0.2.0' but got version %s", chartVersion.Metadata.Version)
|
||||
}
|
||||
|
||||
if len(chartVersion.Dependencies) != 1 {
|
||||
t.Fatalf("Expect 1 dependency but got %d ones", len(chartVersion.Dependencies))
|
||||
}
|
||||
|
||||
if len(chartVersion.Values) != 99 {
|
||||
t.Fatalf("Expect 99 k-v values but got %d", len(chartVersion.Values))
|
||||
}
|
||||
}
|
||||
|
||||
//Test get /api/:repo/charts/:chart_name/:version with none-existing version
|
||||
func TestGetChartVersionWithError(t *testing.T) {
|
||||
_, err := httpClient.GetContent(fmt.Sprintf("%s/api/repo1/charts/harbor/1.0.0", getTheAddrOfFrontServer()))
|
||||
if err == nil {
|
||||
t.Fatal("Expect an error but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
//Get /api/repo1/charts/harbor
|
||||
//401 will be rewritten to 500 with specified error
|
||||
func TestResponseRewrite(t *testing.T) {
|
||||
response, err := http.Get(fmt.Sprintf("%s/api/repo1/charts/harbor", getTheAddrOfFrontServer()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if response.StatusCode != http.StatusInternalServerError {
|
||||
t.Fatalf("Expect status code 500 but got %d", response.StatusCode)
|
||||
}
|
||||
|
||||
bytes, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("Read bytes from http response failed with error: %s", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
errObj := make(map[string]interface{})
|
||||
if err = json.Unmarshal(bytes, &errObj); err != nil {
|
||||
t.Fatalf("Unmarshal error: %s", err)
|
||||
}
|
||||
|
||||
if msg, ok := errObj["error"]; !ok {
|
||||
t.Fatal("Expect an error message from server but got nothing")
|
||||
} else {
|
||||
if !strings.Contains(msg.(string), "operation request from unauthentic source is rejected") {
|
||||
t.Fatal("Missing the required error message")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Clear environments
|
||||
func TestStopServers(t *testing.T) {
|
||||
stopMockServers()
|
||||
}
|
||||
|
||||
//Utility method for getting index yaml file
|
||||
func getIndexYaml(path string) (*helm_repo.IndexFile, error) {
|
||||
content, err := httpClient.GetContent(fmt.Sprintf("%s%s", getTheAddrOfFrontServer(), path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
indexFile := &helm_repo.IndexFile{}
|
||||
if err := yaml.Unmarshal(content, indexFile); err != nil {
|
||||
return nil, fmt.Errorf("Unmarshal error: %s", err)
|
||||
}
|
||||
|
||||
if indexFile == nil {
|
||||
return nil, fmt.Errorf("Got nil index yaml file")
|
||||
}
|
||||
|
||||
return indexFile, nil
|
||||
}
|
@ -79,7 +79,7 @@ func (mh *ManipulationHandler) GetChartVersion(w http.ResponseWriter, req *http.
|
||||
//NOT hit!!
|
||||
|
||||
//TODO:
|
||||
namespace := "repo2"
|
||||
namespace := "repo1"
|
||||
content, err := mh.getChartVersionContent(namespace, chartV.URLs[0])
|
||||
if err != nil {
|
||||
writeInternalError(w, err)
|
||||
|
@ -36,7 +36,8 @@ import (
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver/admiral"
|
||||
)
|
||||
|
||||
type key string
|
||||
//ContextValueKey for content value
|
||||
type ContextValueKey string
|
||||
|
||||
type pathMethod struct {
|
||||
path string
|
||||
@ -44,8 +45,11 @@ type pathMethod struct {
|
||||
}
|
||||
|
||||
const (
|
||||
securCtxKey key = "harbor_security_context"
|
||||
pmKey key = "harbor_project_manager"
|
||||
//SecurCtxKey is context value key for security context
|
||||
SecurCtxKey ContextValueKey = "harbor_security_context"
|
||||
|
||||
//PmKey is context value key for the project manager
|
||||
PmKey ContextValueKey = "harbor_project_manager"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -307,8 +311,8 @@ func (u *unauthorizedReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||
}
|
||||
|
||||
func setSecurCtxAndPM(req *http.Request, ctx security.Context, pm promgr.ProjectManager) {
|
||||
addToReqContext(req, securCtxKey, ctx)
|
||||
addToReqContext(req, pmKey, pm)
|
||||
addToReqContext(req, SecurCtxKey, ctx)
|
||||
addToReqContext(req, PmKey, pm)
|
||||
}
|
||||
|
||||
func addToReqContext(req *http.Request, key, value interface{}) {
|
||||
@ -321,7 +325,7 @@ func GetSecurityContext(req *http.Request) (security.Context, error) {
|
||||
return nil, fmt.Errorf("request is nil")
|
||||
}
|
||||
|
||||
ctx := req.Context().Value(securCtxKey)
|
||||
ctx := req.Context().Value(SecurCtxKey)
|
||||
if ctx == nil {
|
||||
return nil, fmt.Errorf("the security context got from request is nil")
|
||||
}
|
||||
@ -340,7 +344,7 @@ func GetProjectManager(req *http.Request) (promgr.ProjectManager, error) {
|
||||
return nil, fmt.Errorf("request is nil")
|
||||
}
|
||||
|
||||
pm := req.Context().Value(pmKey)
|
||||
pm := req.Context().Value(PmKey)
|
||||
if pm == nil {
|
||||
return nil, fmt.Errorf("the project manager got from request is nil")
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ func projectManager(ctx *beegoctx.Context) interface{} {
|
||||
if ctx.Request == nil {
|
||||
return nil
|
||||
}
|
||||
return ctx.Request.Context().Value(pmKey)
|
||||
return ctx.Request.Context().Value(PmKey)
|
||||
}
|
||||
|
||||
func TestGetSecurityContext(t *testing.T) {
|
||||
@ -310,7 +310,7 @@ func TestGetSecurityContext(t *testing.T) {
|
||||
req, err = http.NewRequest("", "", nil)
|
||||
assert.Nil(t, err)
|
||||
req = req.WithContext(context.WithValue(req.Context(),
|
||||
securCtxKey, "test"))
|
||||
SecurCtxKey, "test"))
|
||||
ctx, err = GetSecurityContext(req)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
@ -318,7 +318,7 @@ func TestGetSecurityContext(t *testing.T) {
|
||||
req, err = http.NewRequest("", "", nil)
|
||||
assert.Nil(t, err)
|
||||
req = req.WithContext(context.WithValue(req.Context(),
|
||||
securCtxKey, local.NewSecurityContext(nil, nil)))
|
||||
SecurCtxKey, local.NewSecurityContext(nil, nil)))
|
||||
ctx, err = GetSecurityContext(req)
|
||||
assert.Nil(t, err)
|
||||
_, ok := ctx.(security.Context)
|
||||
@ -340,7 +340,7 @@ func TestGetProjectManager(t *testing.T) {
|
||||
req, err = http.NewRequest("", "", nil)
|
||||
assert.Nil(t, err)
|
||||
req = req.WithContext(context.WithValue(req.Context(),
|
||||
pmKey, "test"))
|
||||
PmKey, "test"))
|
||||
pm, err = GetProjectManager(req)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
@ -348,7 +348,7 @@ func TestGetProjectManager(t *testing.T) {
|
||||
req, err = http.NewRequest("", "", nil)
|
||||
assert.Nil(t, err)
|
||||
req = req.WithContext(context.WithValue(req.Context(),
|
||||
pmKey, promgr.NewDefaultProjectManager(driver_local.NewDriver(), true)))
|
||||
PmKey, promgr.NewDefaultProjectManager(driver_local.NewDriver(), true)))
|
||||
pm, err = GetProjectManager(req)
|
||||
assert.Nil(t, err)
|
||||
_, ok := pm.(promgr.ProjectManager)
|
||||
|
Loading…
Reference in New Issue
Block a user