harbor/src/replication/adapter/native/adapter_test.go
Wenkai Yin 5925e0862d Replicate tag deletion between Harbor instances
This commit introduces the tag deletion as a new capability for registry adapters, and currently only Harbor supports it

Signed-off-by: Wenkai Yin <yinw@vmware.com>
2020-03-17 09:27:02 +08:00

361 lines
7.9 KiB
Go

// Copyright Project Harbor Authors
//
// 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 native
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/goharbor/harbor/src/common/utils/test"
"github.com/goharbor/harbor/src/replication/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_native_Info(t *testing.T) {
var registry = &model.Registry{URL: "abc"}
adapter := NewAdapter(registry)
assert.NotNil(t, adapter)
info, err := adapter.Info()
assert.Nil(t, err)
assert.NotNil(t, info)
assert.Equal(t, model.RegistryTypeDockerRegistry, info.Type)
assert.Equal(t, 1, len(info.SupportedResourceTypes))
assert.Equal(t, 2, len(info.SupportedResourceFilters))
assert.Equal(t, 2, len(info.SupportedTriggers))
assert.Equal(t, model.ResourceTypeImage, info.SupportedResourceTypes[0])
}
func Test_native_PrepareForPush(t *testing.T) {
var registry = &model.Registry{URL: "abc"}
adapter := NewAdapter(registry)
assert.NotNil(t, adapter)
err := adapter.PrepareForPush(nil)
assert.Nil(t, err)
}
func mockNativeRegistry() (mock *httptest.Server) {
return test.NewServer(
&test.RequestHandlerMapping{
Method: http.MethodGet,
Pattern: "/v2/_catalog",
Handler: func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"repositories":["test/a1","test/b2","test/c3/3level"]}`))
},
},
&test.RequestHandlerMapping{
Method: http.MethodGet,
Pattern: "/v2/test/a1/tags/list",
Handler: func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"name":"test/a1","tags":["tag11"]}`))
},
},
&test.RequestHandlerMapping{
Method: http.MethodGet,
Pattern: "/v2/test/b2/tags/list",
Handler: func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"name":"test/b2","tags":["tag11","tag2","tag13"]}`))
},
},
&test.RequestHandlerMapping{
Method: http.MethodGet,
Pattern: "/v2/test/c3/3level/tags/list",
Handler: func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"name":"test/c3/3level","tags":["tag4"]}`))
},
},
)
}
func Test_native_FetchArtifacts(t *testing.T) {
var mock = mockNativeRegistry()
defer mock.Close()
fmt.Println("mockNativeRegistry URL: ", mock.URL)
var registry = &model.Registry{
Type: model.RegistryTypeDockerRegistry,
URL: mock.URL,
Insecure: true,
}
adapter := NewAdapter(registry)
assert.NotNil(t, adapter)
tests := []struct {
name string
filters []*model.Filter
want []*model.Resource
wantErr bool
}{
{
name: "repository not exist",
filters: []*model.Filter{
{
Type: model.FilterTypeName,
Value: "b1",
},
},
wantErr: false,
},
{
name: "tag not exist",
filters: []*model.Filter{
{
Type: model.FilterTypeTag,
Value: "this_tag_not_exist_in_the_mock_server",
},
},
wantErr: false,
},
{
name: "no filters",
filters: []*model.Filter{},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/a1"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
},
},
},
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/b2"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
{
Tags: []string{"tag2"},
},
{
Tags: []string{"tag13"},
},
},
},
},
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/c3/3level"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag4"},
},
},
},
},
},
wantErr: false,
},
{
name: "only special repository",
filters: []*model.Filter{
{
Type: model.FilterTypeName,
Value: "test/a1",
},
},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/a1"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
},
},
},
},
wantErr: false,
},
{
name: "only special tag",
filters: []*model.Filter{
{
Type: model.FilterTypeTag,
Value: "tag11",
},
},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/a1"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
},
},
},
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/b2"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
},
},
},
},
wantErr: false,
},
{
name: "special repository and special tag",
filters: []*model.Filter{
{
Type: model.FilterTypeName,
Value: "test/b2",
},
{
Type: model.FilterTypeTag,
Value: "tag2",
},
},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/b2"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag2"},
},
},
},
},
},
wantErr: false,
},
{
name: "only wildcard repository",
filters: []*model.Filter{
{
Type: model.FilterTypeName,
Value: "test/b*",
},
},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/b2"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
{
Tags: []string{"tag2"},
},
{
Tags: []string{"tag13"},
},
},
},
},
},
wantErr: false,
},
{
name: "only wildcard tag",
filters: []*model.Filter{
{
Type: model.FilterTypeTag,
Value: "tag1*",
},
},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/a1"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
},
},
},
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/b2"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
{
Tags: []string{"tag13"},
},
},
},
},
},
wantErr: false,
},
{
name: "wildcard repository and wildcard tag",
filters: []*model.Filter{
{
Type: model.FilterTypeName,
Value: "test/b*",
},
{
Type: model.FilterTypeTag,
Value: "tag1*",
},
},
want: []*model.Resource{
{
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "test/b2"},
Artifacts: []*model.Artifact{
{
Tags: []string{"tag11"},
},
{
Tags: []string{"tag13"},
},
},
},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var resources, err = adapter.FetchArtifacts(tt.filters)
if tt.wantErr {
require.Len(t, resources, 0)
require.NotNil(t, err)
} else {
require.Equal(t, len(tt.want), len(resources))
for i, resource := range resources {
require.NotNil(t, resource.Metadata)
assert.Equal(t, tt.want[i].Metadata.Repository, resource.Metadata.Repository)
assert.ElementsMatch(t, tt.want[i].Metadata.Artifacts, resource.Metadata.Artifacts)
}
}
})
}
}