|
|
|
@ -1,3 +1,19 @@
|
|
|
|
|
/*
|
|
|
|
|
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 URL handles Helm-DM URLs
|
|
|
|
|
|
|
|
|
|
Helm uses three kinds of URLs:
|
|
|
|
@ -14,11 +30,16 @@ import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/url"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"regexp"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// ErrLocal indicates that a local URL was used as a remote URL.
|
|
|
|
|
var ErrLocal = errors.New("cannot use local URL as remote")
|
|
|
|
|
|
|
|
|
|
// ErrRemote indicates that a remote URL was used as a local URL.
|
|
|
|
|
var ErrRemote = errors.New("cannot use remote URL as local")
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
SchemeHTTP = "http"
|
|
|
|
|
SchemeHTTPS = "https"
|
|
|
|
@ -61,31 +82,23 @@ type URL struct {
|
|
|
|
|
|
|
|
|
|
func Parse(path string) (*URL, error) {
|
|
|
|
|
|
|
|
|
|
// Check for absolute or relative path.
|
|
|
|
|
if path[0] == '.' || path[0] == '/' {
|
|
|
|
|
return &URL{
|
|
|
|
|
LocalRef: path,
|
|
|
|
|
isLocal: true,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Do we want to support file:///foo/bar.tgz?
|
|
|
|
|
if strings.HasPrefix(path, SchemeFile+":") {
|
|
|
|
|
path := strings.TrimPrefix(path, SchemeFile+":")
|
|
|
|
|
return &URL{
|
|
|
|
|
LocalRef: filepath.Clean(path),
|
|
|
|
|
isLocal: true,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
//if strings.HasPrefix(path, SchemeFile+":") {
|
|
|
|
|
//path := strings.TrimPrefix(path, SchemeFile+":")
|
|
|
|
|
//return &URL{
|
|
|
|
|
//LocalRef: filepath.Clean(path),
|
|
|
|
|
//isLocal: true,
|
|
|
|
|
//original: path,
|
|
|
|
|
//}, nil
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
u, err := url.Parse(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// Short name
|
|
|
|
|
if u.Scheme == SchemeHelm {
|
|
|
|
|
|
|
|
|
|
switch u.Scheme {
|
|
|
|
|
case SchemeHelm:
|
|
|
|
|
parts := strings.SplitN(u.Opaque, "/", 3)
|
|
|
|
|
if len(parts) < 3 {
|
|
|
|
|
return nil, fmt.Errorf("both bucket and chart name are required in %s: %s", path, u.Path)
|
|
|
|
@ -99,27 +112,44 @@ func Parse(path string) (*URL, error) {
|
|
|
|
|
Version: u.Fragment,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Long name
|
|
|
|
|
parts := strings.SplitN(u.Path, "/", 3)
|
|
|
|
|
if len(parts) < 3 {
|
|
|
|
|
return nil, fmt.Errorf("both bucket and chart name are required in %s", path)
|
|
|
|
|
}
|
|
|
|
|
case SchemeHTTP, SchemeHTTPS:
|
|
|
|
|
// Long name
|
|
|
|
|
parts := strings.SplitN(u.Path, "/", 3)
|
|
|
|
|
if len(parts) < 3 {
|
|
|
|
|
return nil, fmt.Errorf("both bucket and chart name are required in %s", path)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name, version, err := parseTarName(parts[2])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
name, version, err := parseTarName(parts[2])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &URL{
|
|
|
|
|
Scheme: u.Scheme,
|
|
|
|
|
Host: u.Host,
|
|
|
|
|
Bucket: parts[1],
|
|
|
|
|
Name: name,
|
|
|
|
|
Version: version,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
case SchemeFile:
|
|
|
|
|
return &URL{
|
|
|
|
|
LocalRef: u.Path,
|
|
|
|
|
isLocal: true,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
default:
|
|
|
|
|
// In this case...
|
|
|
|
|
// - if the path is relative or absolute, return it as-is.
|
|
|
|
|
// - if it's a URL of an unknown scheme, return it as is.
|
|
|
|
|
return &URL{
|
|
|
|
|
LocalRef: path,
|
|
|
|
|
isLocal: true,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
|
|
|
|
|
return &URL{
|
|
|
|
|
Scheme: u.Scheme,
|
|
|
|
|
Host: u.Host,
|
|
|
|
|
Bucket: parts[1],
|
|
|
|
|
Name: name,
|
|
|
|
|
Version: version,
|
|
|
|
|
original: path,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsLocal returns true if this is a local path.
|
|
|
|
@ -134,9 +164,6 @@ func (u *URL) Local() (string, error) {
|
|
|
|
|
return u.LocalRef, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ErrLocal = errors.New("cannot use local URL as remote")
|
|
|
|
|
var ErrRemote = errors.New("cannot use remote URL as local")
|
|
|
|
|
|
|
|
|
|
// Short returns a short form URL.
|
|
|
|
|
//
|
|
|
|
|
// This will return an error if the URL references a local chart.
|
|
|
|
|