Files
kubesphere/pkg/models/registries/registry_client.go
zhuxiaoyang da074e22bd remove schema if requiredss and add Check SSL
Signed-off-by: zhuxiaoyang <sunzhu@yunify.com>
2020-01-16 11:27:17 +08:00

164 lines
3.7 KiB
Go

package registries
import (
"compress/gzip"
"errors"
"fmt"
"github.com/docker/docker/api/types"
"io"
"io/ioutil"
log "k8s.io/klog"
"net/http"
"net/url"
"regexp"
"strings"
"time"
)
const (
// DefaultDockerRegistry is the default docker registry address.
DefaultDockerRegistry = "https://registry-1.docker.io"
DefaultDockerHub = "docker.io"
DefaultTimeout = 30 * time.Second
)
var (
bearerRegex = regexp.MustCompile(
`^\s*Bearer\s+(.*)$`)
basicRegex = regexp.MustCompile(`^\s*Basic\s+.*$`)
// ErrBasicAuth indicates that the repository requires basic rather than token authentication.
ErrBasicAuth = errors.New("basic auth required")
gcrMatcher = regexp.MustCompile(`https://([a-z]+\.|)gcr\.io/`)
)
// Registry defines the client for retrieving information from the registry API.
type Registry struct {
URL string
Domain string
Username string
Password string
Client *http.Client
Opt RegistryOpt
}
// Opt holds the options for a new registry.
type RegistryOpt struct {
Domain string
Timeout time.Duration
Headers map[string]string
UseSSL bool
}
type authToken struct {
Token string `json:"token"`
AccessToken string `json:"access_token"`
}
type authService struct {
Realm *url.URL
Service string
Scope []string
}
func CreateRegistryClient(username, password, domain string, useSSL bool) (*Registry, error) {
authDomain := domain
auth, err := GetAuthConfig(username, password, authDomain)
if err != nil {
log.Error(err)
return nil, err
}
// Create the registry client.
return New(auth, RegistryOpt{
Domain: domain,
UseSSL: useSSL,
})
}
// GetAuthConfig returns the docker registry AuthConfig.
func GetAuthConfig(username, password, registry string) (types.AuthConfig, error) {
registry = setDefaultRegistry(registry)
if username != "" && password != "" {
return types.AuthConfig{
Username: username,
Password: password,
ServerAddress: registry,
}, nil
}
return types.AuthConfig{
ServerAddress: registry,
}, nil
}
func setDefaultRegistry(serverAddress string) string {
if serverAddress == DefaultDockerHub || serverAddress == "" {
serverAddress = DefaultDockerRegistry
}
return serverAddress
}
func newFromTransport(auth types.AuthConfig, opt RegistryOpt) (*Registry, error) {
if len(opt.Domain) < 1 || opt.Domain == DefaultDockerHub {
opt.Domain = auth.ServerAddress
}
registryUrl := strings.TrimSuffix(opt.Domain, "/")
if !strings.HasPrefix(registryUrl, "http://") && !strings.HasPrefix(registryUrl, "https://") {
if opt.UseSSL {
registryUrl = "https://" + registryUrl
} else {
registryUrl = "http://" + registryUrl
}
}
registryURL, _ := url.Parse(registryUrl)
registry := &Registry{
URL: registryURL.String(),
Domain: registryURL.Host,
Client: &http.Client{
Timeout: DefaultTimeout,
},
Username: auth.Username,
Password: auth.Password,
Opt: opt,
}
return registry, nil
}
// url returns a registry URL with the passed arguements concatenated.
func (r *Registry) url(pathTemplate string, args ...interface{}) string {
pathSuffix := fmt.Sprintf(pathTemplate, args...)
url := fmt.Sprintf("%s%s", r.URL, pathSuffix)
return url
}
// New creates a new Registry struct with the given URL and credentials.
func New(auth types.AuthConfig, opt RegistryOpt) (*Registry, error) {
return newFromTransport(auth, opt)
}
// Decompress response.body.
func GetRespBody(resp *http.Response) ([]byte, error) {
var reader io.ReadCloser
if resp.Header.Get("Content-Encoding") == "gzip" {
reader, _ = gzip.NewReader(resp.Body)
} else {
reader = resp.Body
}
resBody, err := ioutil.ReadAll(reader)
if err != nil {
log.Error(err)
return nil, err
}
return resBody, err
}