mirror of https://github.com/helm/helm
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
6.6 KiB
238 lines
6.6 KiB
9 years ago
|
/*
|
||
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||
|
|
||
|
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 registry
|
||
|
|
||
|
import (
|
||
|
"github.com/google/go-github/github"
|
||
|
"github.com/kubernetes/deployment-manager/common"
|
||
|
"github.com/kubernetes/deployment-manager/util"
|
||
|
|
||
|
"fmt"
|
||
|
"net/url"
|
||
|
"regexp"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
// RegistryProvider returns factories for creating registry clients.
|
||
|
type RegistryProvider interface {
|
||
|
GetRegistryByShortURL(URL string) (Registry, error)
|
||
|
GetRegistryByName(registryName string) (Registry, error)
|
||
|
GetGithubRegistry(cr common.Registry) (GithubRegistry, error)
|
||
|
}
|
||
|
|
||
|
func NewDefaultRegistryProvider() RegistryProvider {
|
||
|
registries := make(map[string]Registry)
|
||
|
rs := NewInmemRegistryService()
|
||
|
return &DefaultRegistryProvider{registries: registries, rs: rs}
|
||
|
}
|
||
|
|
||
|
type DefaultRegistryProvider struct {
|
||
|
sync.RWMutex
|
||
|
registries map[string]Registry
|
||
|
rs common.RegistryService
|
||
|
}
|
||
|
|
||
|
// Deprecated: Use GetRegistryByShortURL instead.
|
||
|
func (drp DefaultRegistryProvider) GetRegistryByURL(URL string) (Registry, error) {
|
||
|
return drp.GetRegistryByShortURL(URL)
|
||
|
}
|
||
|
|
||
|
func (drp DefaultRegistryProvider) GetRegistryByShortURL(URL string) (Registry, error) {
|
||
|
drp.RLock()
|
||
|
defer drp.RUnlock()
|
||
|
|
||
|
r := drp.findRegistryByShortURL(URL)
|
||
|
if r == nil {
|
||
|
cr, err := drp.rs.GetByURL(URL)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
r, err := drp.GetGithubRegistry(*cr)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
drp.registries[r.GetRegistryName()] = r
|
||
|
}
|
||
|
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
func (drp DefaultRegistryProvider) findRegistryByShortURL(URL string) Registry {
|
||
|
for _, r := range drp.registries {
|
||
|
if strings.HasPrefix(URL, r.GetRegistryShortURL()) {
|
||
|
return r
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (drp DefaultRegistryProvider) GetRegistryByName(registryName string) (Registry, error) {
|
||
|
drp.RLock()
|
||
|
defer drp.RUnlock()
|
||
|
|
||
|
r, ok := drp.registries[registryName]
|
||
|
if !ok {
|
||
|
cr, err := drp.rs.Get(registryName)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
r, err := drp.GetGithubRegistry(*cr)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
drp.registries[r.GetRegistryName()] = r
|
||
|
}
|
||
|
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
func ParseRegistryFormat(rf common.RegistryFormat) map[common.RegistryFormat]bool {
|
||
|
split := strings.Split(string(rf), ";")
|
||
|
var result map[common.RegistryFormat]bool
|
||
|
for _, format := range split {
|
||
|
result[common.RegistryFormat(format)] = true
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func (drp DefaultRegistryProvider) GetGithubRegistry(cr common.Registry) (GithubRegistry, error) {
|
||
|
if cr.Type == common.GithubRegistryType {
|
||
|
fMap := ParseRegistryFormat(cr.Format)
|
||
|
if fMap[common.UnversionedRegistry] && fMap[common.OneLevelRegistry] {
|
||
|
return NewGithubPackageRegistry(cr.Name, cr.URL, github.NewClient(nil))
|
||
|
}
|
||
|
|
||
|
if fMap[common.VersionedRegistry] && fMap[common.CollectionRegistry] {
|
||
|
return NewGithubTemplateRegistry(cr.Name, cr.URL, github.NewClient(nil))
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("unknown registry format: %s", cr.Format)
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("unknown registry type: %s", cr.Type)
|
||
|
}
|
||
|
|
||
|
// RE for a registry type that does support versions and has collections.
|
||
|
var TemplateRegistryMatcher = regexp.MustCompile("github.com/(.*)/(.*)/(.*)/(.*):(.*)")
|
||
|
|
||
|
// RE for a registry type that does not support versions and does not have collections.
|
||
|
var PackageRegistryMatcher = regexp.MustCompile("github.com/(.*)/(.*)/(.*)")
|
||
|
|
||
|
// IsGithubShortType returns whether a given type is a type description in a short format to a github repository type.
|
||
|
// For now, this means using github types:
|
||
|
// github.com/owner/repo/qualifier/type:version
|
||
|
// for example:
|
||
|
// github.com/kubernetes/application-dm-templates/storage/redis:v1
|
||
|
func IsGithubShortType(t string) bool {
|
||
|
return TemplateRegistryMatcher.MatchString(t)
|
||
|
}
|
||
|
|
||
|
// IsGithubShortPackageType returns whether a given type is a type description in a short format to a github
|
||
|
// package repository type.
|
||
|
// For now, this means using github types:
|
||
|
// github.com/owner/repo/type
|
||
|
// for example:
|
||
|
// github.com/helm/charts/cassandra
|
||
|
func IsGithubShortPackageType(t string) bool {
|
||
|
return PackageRegistryMatcher.MatchString(t)
|
||
|
}
|
||
|
|
||
|
// GetDownloadURLs checks a type to see if it is either a short git hub url or a fully specified URL
|
||
|
// and returns the URLs that should be used to fetch it. If the url is not fetchable (primitive type
|
||
|
// for example), it returns an empty slice.
|
||
|
func GetDownloadURLs(rp RegistryProvider, t string) ([]string, error) {
|
||
|
if IsGithubShortType(t) {
|
||
|
return ShortTypeToDownloadURLs(rp, t)
|
||
|
} else if IsGithubShortPackageType(t) {
|
||
|
return ShortTypeToPackageDownloadURLs(rp, t)
|
||
|
} else if util.IsHttpUrl(t) {
|
||
|
result, err := url.Parse(t)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("cannot parse download URL %s: %s", t, err)
|
||
|
}
|
||
|
|
||
|
return []string{result.String()}, nil
|
||
|
}
|
||
|
|
||
|
return []string{}, nil
|
||
|
}
|
||
|
|
||
|
// ShortTypeToDownloadURLs converts a github URL into downloadable URL from github.
|
||
|
// Input must be of the type and is assumed to have been validated before this call:
|
||
|
// github.com/owner/repo/qualifier/type:version
|
||
|
// for example:
|
||
|
// github.com/kubernetes/application-dm-templates/storage/redis:v1
|
||
|
func ShortTypeToDownloadURLs(rp RegistryProvider, t string) ([]string, error) {
|
||
|
m := TemplateRegistryMatcher.FindStringSubmatch(t)
|
||
|
if len(m) != 6 {
|
||
|
return nil, fmt.Errorf("cannot parse short github url: %s", t)
|
||
|
}
|
||
|
|
||
|
r, err := rp.GetRegistryByShortURL(t)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
tt, err := NewType(m[3], m[4], m[5])
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
urls, err := r.GetDownloadURLs(tt)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return util.ConvertURLsToStrings(urls), err
|
||
|
}
|
||
|
|
||
|
// ShortTypeToPackageDownloadURLs converts a github URL into downloadable URLs from github.
|
||
|
// Input must be of the type and is assumed to have been validated before this call:
|
||
|
// github.com/owner/repo/type
|
||
|
// for example:
|
||
|
// github.com/helm/charts/cassandra
|
||
|
func ShortTypeToPackageDownloadURLs(rp RegistryProvider, t string) ([]string, error) {
|
||
|
m := PackageRegistryMatcher.FindStringSubmatch(t)
|
||
|
if len(m) != 4 {
|
||
|
return nil, fmt.Errorf("Failed to parse short github url: %s", t)
|
||
|
}
|
||
|
|
||
|
r, err := rp.GetRegistryByShortURL(t)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
tt, err := NewType("", m[3], "")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
urls, err := r.GetDownloadURLs(tt)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return util.ConvertURLsToStrings(urls), err
|
||
|
}
|