remove schema if requiredss and add Check SSL
Signed-off-by: zhuxiaoyang <sunzhu@yunify.com>
This commit is contained in:
@@ -21,6 +21,7 @@ package registries
|
|||||||
import (
|
import (
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/registries"
|
"kubesphere.io/kubesphere/pkg/models/registries"
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
@@ -68,6 +69,25 @@ func RegistryImageBlob(request *restful.Request, response *restful.Response) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// default use ssl
|
||||||
|
checkSSl := func(serverAddress string) bool {
|
||||||
|
if strings.HasPrefix(serverAddress, "http://") {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(imageName, "http") {
|
||||||
|
dockerurl, err := registries.ParseDockerURL(imageName)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), response)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
imageName = dockerurl.StringWithoutScheme()
|
||||||
|
}
|
||||||
|
|
||||||
// parse image
|
// parse image
|
||||||
image, err := registries.ParseImage(imageName)
|
image, err := registries.ParseImage(imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -76,8 +96,10 @@ func RegistryImageBlob(request *restful.Request, response *restful.Response) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useSSL := checkSSl(entry.ServerAddress)
|
||||||
|
|
||||||
// Create the registry client.
|
// Create the registry client.
|
||||||
r, err := registries.CreateRegistryClient(entry.Username, entry.Password, image.Domain)
|
r, err := registries.CreateRegistryClient(entry.Username, entry.Password, image.Domain, useSSL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("%+v", err)
|
log.Errorf("%+v", err)
|
||||||
response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
|
response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package registries
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
digest "github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
log "k8s.io/klog"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Image holds information about an image.
|
// Image holds information about an image.
|
||||||
@@ -30,9 +32,28 @@ func (i *Image) Reference() string {
|
|||||||
return i.Tag
|
return i.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DockerURL struct {
|
||||||
|
*url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *DockerURL) StringWithoutScheme() string {
|
||||||
|
u.Scheme = ""
|
||||||
|
s := u.String()
|
||||||
|
return strings.Trim(s, "//")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDockerURL(rawurl string) (*DockerURL, error) {
|
||||||
|
url, err := url.Parse(rawurl)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("%+v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &DockerURL{URL: url}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseImage returns an Image struct with all the values filled in for a given image.
|
// ParseImage returns an Image struct with all the values filled in for a given image.
|
||||||
// example : localhost:5000/nginx:latest, nginx:perl etc.
|
// example : localhost:5000/nginx:latest, nginx:perl etc.
|
||||||
func ParseImage(image string) (Image, error) {
|
func ParseImage(image string) (i Image, err error) {
|
||||||
// Parse the image name and tag.
|
// Parse the image name and tag.
|
||||||
named, err := reference.ParseNormalizedNamed(image)
|
named, err := reference.ParseNormalizedNamed(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -41,7 +62,7 @@ func ParseImage(image string) (Image, error) {
|
|||||||
// Add the latest lag if they did not provide one.
|
// Add the latest lag if they did not provide one.
|
||||||
named = reference.TagNameOnly(named)
|
named = reference.TagNameOnly(named)
|
||||||
|
|
||||||
i := Image{
|
i = Image{
|
||||||
named: named,
|
named: named,
|
||||||
Domain: reference.Domain(named),
|
Domain: reference.Domain(named),
|
||||||
Path: reference.Path(named),
|
Path: reference.Path(named),
|
||||||
|
|||||||
84
pkg/models/registries/image_test.go
Normal file
84
pkg/models/registries/image_test.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package registries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseImage(t *testing.T) {
|
||||||
|
type image struct {
|
||||||
|
ImageName string
|
||||||
|
ExDomain string
|
||||||
|
ExTag string
|
||||||
|
ExPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
testImages := []image{
|
||||||
|
{ImageName: "dockerhub.qingcloud.com/kubesphere/test:v1", ExDomain: "dockerhub.qingcloud.com", ExTag: "v1", ExPath: "kubesphere/test"},
|
||||||
|
{ImageName: "harbor.devops.kubesphere.local:30280/library/tomcat:latest", ExDomain: "harbor.devops.kubesphere.local:30280", ExTag: "latest", ExPath: "library/tomcat"},
|
||||||
|
{ImageName: "zhuxiaoyang/nginx:v1", ExDomain: "docker.io", ExTag: "v1", ExPath: "zhuxiaoyang/nginx"},
|
||||||
|
{ImageName: "nginx", ExDomain: "docker.io", ExTag: "latest", ExPath: "library/nginx"},
|
||||||
|
{ImageName: "nginx:latest", ExDomain: "docker.io", ExTag: "latest", ExPath: "library/nginx"},
|
||||||
|
{ImageName: "kubesphere/ks-account:v2.1.0", ExDomain: "docker.io", ExTag: "v2.1.0", ExPath: "kubesphere/ks-account"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, image := range testImages {
|
||||||
|
res, err := ParseImage(image.ImageName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get err %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Domain != image.ExDomain {
|
||||||
|
t.Fatalf("Doamin got %v, expected %v", res.Domain, image.ExDomain)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Tag != image.ExTag {
|
||||||
|
t.Fatalf("Tag got %v, expected %v", res.Tag, image.ExTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Path != image.ExPath {
|
||||||
|
t.Fatalf("Path got %v, expected %v", res.Path, image.ExPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidImage := []image{
|
||||||
|
{ImageName: "http://docker.io/nginx:latest"},
|
||||||
|
{ImageName: "https://harbor.devops.kubesphere.local:30280/library/tomcat:latest"},
|
||||||
|
{ImageName: "docker.io/nginx:latest:latest"},
|
||||||
|
{ImageName: "nginx:8000:latest"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, image := range invalidImage {
|
||||||
|
_, err := ParseImage(image.ImageName)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Parse invalid image but without get any error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringWithoutScheme(t *testing.T) {
|
||||||
|
type testRawurl struct {
|
||||||
|
Rawurl string
|
||||||
|
ExUrl string
|
||||||
|
}
|
||||||
|
testRawurls := []testRawurl{
|
||||||
|
{"http://dockerhub.qingcloud.com/kubesphere/nginx:v1", "dockerhub.qingcloud.com/kubesphere/nginx:v1"},
|
||||||
|
{"https://dockerhub.qingcloud.com/kubesphere/nginx:v1", "dockerhub.qingcloud.com/kubesphere/nginx:v1"},
|
||||||
|
{"dockerhub.qingcloud.com/kubesphere/nginx:v1", "dockerhub.qingcloud.com/kubesphere/nginx:v1"},
|
||||||
|
{"http://harbor.devops.kubesphere.local:30280/library/tomcat:latest", "harbor.devops.kubesphere.local:30280/library/tomcat:latest"},
|
||||||
|
{"https://harbor.devops.kubesphere.local:30280/library/tomcat:latest", "harbor.devops.kubesphere.local:30280/library/tomcat:latest"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rawurl := range testRawurls {
|
||||||
|
dockerurl, err := ParseDockerURL(rawurl.Rawurl)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get err %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
imageName := dockerurl.StringWithoutScheme()
|
||||||
|
|
||||||
|
if imageName != rawurl.ExUrl {
|
||||||
|
t.Fatalf("imagename got %v, expected %v", imageName, rawurl.ExUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
func TestDigestFromDockerHub(t *testing.T) {
|
func TestDigestFromDockerHub(t *testing.T) {
|
||||||
|
|
||||||
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
||||||
r, err := CreateRegistryClient("", "", "docker.io")
|
r, err := CreateRegistryClient("", "", "docker.io", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get client: %s", err)
|
t.Fatalf("Could not get client: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ type authService struct {
|
|||||||
Scope []string
|
Scope []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateRegistryClient(username, password, domain string) (*Registry, error) {
|
func CreateRegistryClient(username, password, domain string, useSSL bool) (*Registry, error) {
|
||||||
authDomain := domain
|
authDomain := domain
|
||||||
auth, err := GetAuthConfig(username, password, authDomain)
|
auth, err := GetAuthConfig(username, password, authDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -75,6 +75,7 @@ func CreateRegistryClient(username, password, domain string) (*Registry, error)
|
|||||||
// Create the registry client.
|
// Create the registry client.
|
||||||
return New(auth, RegistryOpt{
|
return New(auth, RegistryOpt{
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
|
UseSSL: useSSL,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DockerHub = "docker.io"
|
||||||
|
|
||||||
func TestCreateRegistryClient(t *testing.T) {
|
func TestCreateRegistryClient(t *testing.T) {
|
||||||
type imageInfo struct {
|
type imageInfo struct {
|
||||||
Username string
|
Username string
|
||||||
@@ -11,17 +13,19 @@ func TestCreateRegistryClient(t *testing.T) {
|
|||||||
Domain string
|
Domain string
|
||||||
ExDomain string
|
ExDomain string
|
||||||
ExUrl string
|
ExUrl string
|
||||||
|
UseSSL bool
|
||||||
}
|
}
|
||||||
|
|
||||||
testImages := []imageInfo{
|
testImages := []imageInfo{
|
||||||
{Domain: "kubesphere.io", ExDomain: "kubesphere.io", ExUrl: "http://kubesphere.io"},
|
{Domain: "kubesphere.io", ExDomain: "kubesphere.io", ExUrl: "https://kubesphere.io", UseSSL: true},
|
||||||
{Domain: "127.0.0.1:5000", ExDomain: "127.0.0.1:5000", ExUrl: "http://127.0.0.1:5000"},
|
{Domain: "127.0.0.1:5000", ExDomain: "127.0.0.1:5000", ExUrl: "http://127.0.0.1:5000", UseSSL: false},
|
||||||
{Username: "Username", Password: "Password", Domain: "docker.io", ExDomain: "registry-1.docker.io", ExUrl: "https://registry-1.docker.io"},
|
{Username: "Username", Password: "Password", Domain: DockerHub, ExDomain: "registry-1.docker.io", ExUrl: "https://registry-1.docker.io", UseSSL: true},
|
||||||
{Domain: "harbor.devops.kubesphere.local:30280", ExDomain: "harbor.devops.kubesphere.local:30280", ExUrl: "http://harbor.devops.kubesphere.local:30280"},
|
{Domain: "harbor.devops.kubesphere.local:30280", ExDomain: "harbor.devops.kubesphere.local:30280", ExUrl: "http://harbor.devops.kubesphere.local:30280", UseSSL: false},
|
||||||
|
{Domain: "dockerhub.qingcloud.com/zxytest/s2i-jj:jj", ExDomain: "dockerhub.qingcloud.com", ExUrl: "https://dockerhub.qingcloud.com/zxytest/s2i-jj:jj", UseSSL: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testImage := range testImages {
|
for _, testImage := range testImages {
|
||||||
reg, err := CreateRegistryClient(testImage.Username, testImage.Password, testImage.Domain)
|
reg, err := CreateRegistryClient(testImage.Username, testImage.Password, testImage.Domain, testImage.UseSSL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Get err %s", err)
|
t.Fatalf("Get err %s", err)
|
||||||
}
|
}
|
||||||
@@ -36,8 +40,8 @@ func TestCreateRegistryClient(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
testImage := Image{Domain: DockerHub, Path: "library/alpine", Tag: "latest"}
|
||||||
r, err := CreateRegistryClient("", "", "docker.io")
|
r, err := CreateRegistryClient("", "", DockerHub, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get client: %s", err)
|
t.Fatalf("Could not get client: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (asm authServiceMock) equalTo(v *authService) bool {
|
|||||||
|
|
||||||
func TestToken(t *testing.T) {
|
func TestToken(t *testing.T) {
|
||||||
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
||||||
r, err := CreateRegistryClient("", "", "docker.io")
|
r, err := CreateRegistryClient("", "", "docker.io", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not get registry client: %s", err)
|
t.Fatalf("Could not get registry client: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user