Merge pull request #1774 from soulseen/fix/image

Fix/image
This commit is contained in:
KubeSphere CI Bot
2020-01-16 14:08:00 +08:00
committed by GitHub
7 changed files with 136 additions and 15 deletions

View File

@@ -21,6 +21,7 @@ package registries
import (
"github.com/emicklei/go-restful"
"net/http"
"strings"
"kubesphere.io/kubesphere/pkg/models/registries"
"kubesphere.io/kubesphere/pkg/server/errors"
@@ -68,6 +69,25 @@ func RegistryImageBlob(request *restful.Request, response *restful.Response) {
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
image, err := registries.ParseImage(imageName)
if err != nil {
@@ -76,8 +96,10 @@ func RegistryImageBlob(request *restful.Request, response *restful.Response) {
return
}
useSSL := checkSSl(entry.ServerAddress)
// 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 {
log.Errorf("%+v", err)
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})

View File

@@ -2,9 +2,11 @@ package registries
import (
"fmt"
"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.
@@ -30,9 +32,28 @@ func (i *Image) Reference() string {
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.
// 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.
named, err := reference.ParseNormalizedNamed(image)
if err != nil {
@@ -41,7 +62,7 @@ func ParseImage(image string) (Image, error) {
// Add the latest lag if they did not provide one.
named = reference.TagNameOnly(named)
i := Image{
i = Image{
named: named,
Domain: reference.Domain(named),
Path: reference.Path(named),

View File

@@ -0,0 +1,73 @@
package registries
import (
"testing"
)
func TestParseImage(t *testing.T) {
type testImage struct {
inputImageName string
ExImage Image
}
testImages := []testImage{
{inputImageName: "dockerhub.qingcloud.com/kubesphere/test:v1", ExImage: Image{Domain: "dockerhub.qingcloud.com", Tag: "v1", Path: "kubesphere/test"}},
{inputImageName: "harbor.devops.kubesphere.local:30280/library/tomcat:latest", ExImage: Image{Domain: "harbor.devops.kubesphere.local:30280", Tag: "latest", Path: "library/tomcat"}},
{inputImageName: "zhuxiaoyang/nginx:v1", ExImage: Image{Domain: "docker.io", Tag: "v1", Path: "zhuxiaoyang/nginx"}},
{inputImageName: "nginx", ExImage: Image{Domain: "docker.io", Tag: "latest", Path: "library/nginx"}},
{inputImageName: "nginx:latest", ExImage: Image{Domain: "docker.io", Tag: "latest", Path: "library/nginx"}},
{inputImageName: "kubesphere/ks-account:v2.1.0", ExImage: Image{Domain: "docker.io", Tag: "v2.1.0", Path: "kubesphere/ks-account"}},
{inputImageName: "http://docker.io/nginx:latest", ExImage: Image{}},
{inputImageName: "https://harbor.devops.kubesphere.local:30280/library/tomcat:latest", ExImage: Image{}},
{inputImageName: "docker.io/nginx:latest:latest", ExImage: Image{}},
{inputImageName: "nginx:8000:latest", ExImage: Image{}},
}
for _, image := range testImages {
res, err := ParseImage(image.inputImageName)
if err != nil {
if res != image.ExImage {
t.Fatalf("Get err %s", err)
}
}
if res.Domain != image.ExImage.Domain {
t.Fatalf("Doamin got %v, expected %v", res.Domain, image.ExImage.Domain)
}
if res.Tag != image.ExImage.Tag {
t.Fatalf("Tag got %v, expected %v", res.Tag, image.ExImage.Tag)
}
if res.Path != image.ExImage.Path {
t.Fatalf("Path got %v, expected %v", res.Path, image.ExImage.Path)
}
}
}
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"},
{"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)
}
}
}

View File

@@ -7,7 +7,7 @@ import (
func TestDigestFromDockerHub(t *testing.T) {
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
r, err := CreateRegistryClient("", "", "docker.io")
r, err := CreateRegistryClient("", "", "docker.io", true)
if err != nil {
t.Fatalf("Could not get client: %s", err)
}

View File

@@ -64,7 +64,7 @@ type authService struct {
Scope []string
}
func CreateRegistryClient(username, password, domain string) (*Registry, error) {
func CreateRegistryClient(username, password, domain string, useSSL bool) (*Registry, error) {
authDomain := domain
auth, err := GetAuthConfig(username, password, authDomain)
if err != nil {
@@ -75,6 +75,7 @@ func CreateRegistryClient(username, password, domain string) (*Registry, error)
// Create the registry client.
return New(auth, RegistryOpt{
Domain: domain,
UseSSL: useSSL,
})
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
)
const DockerHub = "docker.io"
func TestCreateRegistryClient(t *testing.T) {
type imageInfo struct {
Username string
@@ -11,17 +13,19 @@ func TestCreateRegistryClient(t *testing.T) {
Domain string
ExDomain string
ExUrl string
UseSSL bool
}
testImages := []imageInfo{
{Domain: "kubesphere.io", ExDomain: "kubesphere.io", ExUrl: "http://kubesphere.io"},
{Domain: "127.0.0.1:5000", ExDomain: "127.0.0.1:5000", ExUrl: "http://127.0.0.1:5000"},
{Username: "Username", Password: "Password", Domain: "docker.io", ExDomain: "registry-1.docker.io", ExUrl: "https://registry-1.docker.io"},
{Domain: "harbor.devops.kubesphere.local:30280", ExDomain: "harbor.devops.kubesphere.local:30280", ExUrl: "http://harbor.devops.kubesphere.local:30280"},
{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", UseSSL: false},
{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", 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 {
reg, err := CreateRegistryClient(testImage.Username, testImage.Password, testImage.Domain)
reg, err := CreateRegistryClient(testImage.Username, testImage.Password, testImage.Domain, testImage.UseSSL)
if err != nil {
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"}
r, err := CreateRegistryClient("", "", "docker.io")
testImage := Image{Domain: DockerHub, Path: "library/alpine", Tag: "latest"}
r, err := CreateRegistryClient("", "", DockerHub, true)
if err != nil {
t.Fatalf("Could not get client: %s", err)
}

View File

@@ -32,7 +32,7 @@ func (asm authServiceMock) equalTo(v *authService) bool {
func TestToken(t *testing.T) {
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
r, err := CreateRegistryClient("", "", "docker.io")
r, err := CreateRegistryClient("", "", "docker.io", true)
if err != nil {
t.Fatalf("Could not get registry client: %s", err)
}