mirror of https://github.com/helm/helm
commit
4b4d58c8ac
@ -0,0 +1,215 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GithubTemplateRegistry implements the Registry interface and implements a
|
||||
// Deployment Manager templates registry.
|
||||
// A registry root must be a directory that contains all the available templates,
|
||||
// one directory per template. Each template directory then contains version
|
||||
// directories, each of which in turn contains all the files necessary for that
|
||||
// version of the template.
|
||||
//
|
||||
// For example, a template registry containing two versions of redis
|
||||
// (implemented in jinja), and one version of replicatedservice (implemented
|
||||
// in python) would have a directory structure that looks something like this:
|
||||
// qualifier [optional] prefix to a virtual root within the repository.
|
||||
// /redis
|
||||
// /v1
|
||||
// redis.jinja
|
||||
// redis.jinja.schema
|
||||
// /v2
|
||||
// redis.jinja
|
||||
// redis.jinja.schema
|
||||
// /replicatedservice
|
||||
// /v1
|
||||
// replicatedservice.python
|
||||
// replicatedservice.python.schema
|
||||
type GithubTemplateRegistry struct {
|
||||
githubRegistry
|
||||
}
|
||||
|
||||
// NewGithubTemplateRegistry creates a GithubTemplateRegistry.
|
||||
func NewGithubTemplateRegistry(name, shortURL string, service RepositoryService) (*GithubTemplateRegistry, error) {
|
||||
format := fmt.Sprintf("%s;%s", common.VersionedRegistry, common.CollectionRegistry)
|
||||
if service == nil {
|
||||
client := github.NewClient(nil)
|
||||
service = client.Repositories
|
||||
}
|
||||
|
||||
gr, err := newGithubRegistry(name, shortURL, common.RegistryFormat(format), service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GithubTemplateRegistry{githubRegistry: *gr}, nil
|
||||
}
|
||||
|
||||
// ListTypes lists types in this registry whose string values conform to the
|
||||
// supplied regular expression, or all types, if the regular expression is nil.
|
||||
func (g GithubTemplateRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) {
|
||||
// First list all the collections at the top level.
|
||||
collections, err := g.getDirs("")
|
||||
if err != nil {
|
||||
log.Printf("cannot list qualifiers: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var retTypes []Type
|
||||
for _, c := range collections {
|
||||
// Then we need to fetch the versions (directories for this type)
|
||||
types, err := g.getDirs(c)
|
||||
if err != nil {
|
||||
log.Printf("cannot fetch types for collection: %s", c)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, t := range types {
|
||||
path := c + "/" + t
|
||||
// Then we need to fetch the versions (directories for this type)
|
||||
versions, err := g.getDirs(path)
|
||||
if err != nil {
|
||||
log.Printf("cannot fetch versions at path %s", path)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range versions {
|
||||
tt, err := NewType(c, t, v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("malformed type at path %s", path)
|
||||
}
|
||||
|
||||
retTypes = append(retTypes, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if regex != nil {
|
||||
var matchTypes []Type
|
||||
for _, retType := range retTypes {
|
||||
if regex.MatchString(retType.String()) {
|
||||
matchTypes = append(matchTypes, retType)
|
||||
}
|
||||
}
|
||||
|
||||
return matchTypes, nil
|
||||
}
|
||||
|
||||
return retTypes, nil
|
||||
}
|
||||
|
||||
// GetDownloadURLs fetches the download URLs for a given Type and checks for existence of a schema file.
|
||||
func (g GithubTemplateRegistry) GetDownloadURLs(t Type) ([]*url.URL, error) {
|
||||
path, err := g.MakeRepositoryPath(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, dc, _, err := g.service.GetContents(g.owner, g.repository, path, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot list versions at path %s: %v", path, err)
|
||||
}
|
||||
|
||||
var downloadURL, typeName, schemaName string
|
||||
for _, f := range dc {
|
||||
if *f.Type == "file" {
|
||||
if *f.Name == t.Name+".jinja" || *f.Name == t.Name+".py" {
|
||||
typeName = *f.Name
|
||||
downloadURL = *f.DownloadURL
|
||||
}
|
||||
if *f.Name == t.Name+".jinja.schema" || *f.Name == t.Name+".py.schema" {
|
||||
schemaName = *f.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if downloadURL == "" {
|
||||
return nil, fmt.Errorf("cannot find type %s", t.String())
|
||||
}
|
||||
|
||||
if schemaName != typeName+".schema" {
|
||||
return nil, fmt.Errorf("cannot find schema for %s, expected %s", t.String(), typeName+".schema")
|
||||
}
|
||||
|
||||
result, err := url.Parse(downloadURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse URL from %s: %s", downloadURL, err)
|
||||
}
|
||||
|
||||
return []*url.URL{result}, nil
|
||||
}
|
||||
|
||||
func (g GithubTemplateRegistry) getDirs(dir string) ([]string, error) {
|
||||
var path = g.path
|
||||
if dir != "" {
|
||||
path = g.path + "/" + dir
|
||||
}
|
||||
|
||||
_, dc, _, err := g.service.GetContents(g.owner, g.repository, path, nil)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get contents at path: %s: %v", path, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dirs []string
|
||||
for _, entry := range dc {
|
||||
if *entry.Type == "dir" {
|
||||
dirs = append(dirs, *entry.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return dirs, nil
|
||||
}
|
||||
|
||||
func (g GithubTemplateRegistry) mapCollection(collection string) (string, error) {
|
||||
if strings.ContainsAny(collection, "/") {
|
||||
return "", fmt.Errorf("collection must not contain slashes, got %s", collection)
|
||||
}
|
||||
// TODO(vaikas): Implement lookup from the root metadata file to map collection to a path
|
||||
return collection, nil
|
||||
}
|
||||
|
||||
// MakeRepositoryPath constructs a github path to a given type based on a repository, and type name and version.
|
||||
// The returned repository path will be of the form:
|
||||
// [GithubTemplateRegistry.path/][Type.Collection]/Type.Name/Type.Version
|
||||
// Type.Collection will be mapped using mapCollection in the future, for now it's a straight
|
||||
// 1:1 mapping (if given)
|
||||
func (g GithubTemplateRegistry) MakeRepositoryPath(t Type) (string, error) {
|
||||
// First map the collection
|
||||
collection, err := g.mapCollection(t.Collection)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Construct the return path
|
||||
p := ""
|
||||
if len(g.path) > 0 {
|
||||
p += g.path + "/"
|
||||
}
|
||||
if len(collection) > 0 {
|
||||
p += collection + "/"
|
||||
}
|
||||
return p + t.Name + "/" + t.GetVersion(), nil
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
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/kubernetes/deployment-manager/common"
|
||||
"github.com/kubernetes/deployment-manager/util"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type inmemRegistryService struct {
|
||||
registries map[string]*common.AuthenticatedRegistry
|
||||
}
|
||||
|
||||
func NewInmemRegistryService() common.RegistryService {
|
||||
rs := &inmemRegistryService{
|
||||
registries: make(map[string]*common.AuthenticatedRegistry),
|
||||
}
|
||||
|
||||
pFormat := fmt.Sprintf("%s;%s", common.UnversionedRegistry, common.OneLevelRegistry)
|
||||
rs.Create(&common.Registry{
|
||||
Name: "charts",
|
||||
Type: common.GithubRegistryType,
|
||||
URL: "github.com/helm/charts",
|
||||
Format: common.RegistryFormat(pFormat),
|
||||
})
|
||||
|
||||
tFormat := fmt.Sprintf("%s;%s", common.VersionedRegistry, common.CollectionRegistry)
|
||||
rs.Create(&common.Registry{
|
||||
Name: "application-dm-templates",
|
||||
Type: common.GithubRegistryType,
|
||||
URL: "github.com/kubernetes/application-dm-templates",
|
||||
Format: common.RegistryFormat(tFormat),
|
||||
})
|
||||
|
||||
return rs
|
||||
}
|
||||
|
||||
// List returns the list of known registries.
|
||||
func (rs *inmemRegistryService) List() ([]*common.Registry, error) {
|
||||
ret := []*common.Registry{}
|
||||
for _, r := range rs.registries {
|
||||
ret = append(ret, &r.Registry)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Create creates an authenticated registry.
|
||||
func (rs *inmemRegistryService) Create(registry *common.Registry) error {
|
||||
rs.registries[registry.Name] = &common.AuthenticatedRegistry{Registry: *registry}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get returns a registry with a given name.
|
||||
func (rs *inmemRegistryService) Get(name string) (*common.Registry, error) {
|
||||
r, ok := rs.registries[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to find registry named %s", name)
|
||||
}
|
||||
|
||||
return &r.Registry, nil
|
||||
}
|
||||
|
||||
// GetAuthenticatedRegistry returns an authenticated registry with a given name.
|
||||
func (rs *inmemRegistryService) GetAuthenticatedRegistry(name string) (*common.AuthenticatedRegistry, error) {
|
||||
r, ok := rs.registries[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to find registry named %s", name)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Create deletes the authenticated registry with a given name.
|
||||
func (rs *inmemRegistryService) Delete(name string) error {
|
||||
_, ok := rs.registries[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to find registry named %s", name)
|
||||
}
|
||||
|
||||
delete(rs.registries, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetByURL returns a registry that handles the types for a given URL.
|
||||
func (rs *inmemRegistryService) GetByURL(URL string) (*common.Registry, error) {
|
||||
trimmed := util.TrimURLScheme(URL)
|
||||
for _, r := range rs.registries {
|
||||
if strings.HasPrefix(trimmed, util.TrimURLScheme(r.URL)) {
|
||||
return &r.Registry, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Failed to find registry for url: %s", URL)
|
||||
}
|
||||
|
||||
// GetAuthenticatedRegistryByURL returns an authenticated registry that handles the types for a given URL.
|
||||
func (rs *inmemRegistryService) GetAuthenticatedRegistryByURL(URL string) (*common.AuthenticatedRegistry, error) {
|
||||
trimmed := util.TrimURLScheme(URL)
|
||||
for _, r := range rs.registries {
|
||||
if strings.HasPrefix(trimmed, util.TrimURLScheme(r.URL)) {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Failed to find registry for url: %s", URL)
|
||||
}
|
||||
|
||||
// Set the credential for a registry.
|
||||
func (rs *inmemRegistryService) SetCredential(name string, credential common.RegistryCredential) error {
|
||||
r, ok := rs.registries[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to find registry named %s", name)
|
||||
}
|
||||
|
||||
r.Credential = credential
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the credential for a registry.
|
||||
func (rs *inmemRegistryService) GetCredential(name string) (common.RegistryCredential, error) {
|
||||
r, ok := rs.registries[name]
|
||||
if !ok {
|
||||
return common.RegistryCredential{}, fmt.Errorf("Failed to find registry named %s", name)
|
||||
}
|
||||
|
||||
return r.Credential, nil
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/kubernetes/deployment-manager/common"
|
||||
)
|
||||
|
||||
type inmemRepositoryService struct {
|
||||
repositories map[string]*common.Registry
|
||||
}
|
||||
|
||||
func NewInmemRepositoryService() RegistryService {
|
||||
rs := &inmemRepositoryService{
|
||||
repositories: make(map[string]*common.Registry),
|
||||
}
|
||||
rs.Create(&common.Registry{
|
||||
Name: "charts",
|
||||
Type: common.Github,
|
||||
URL: "github.com/helm/charts",
|
||||
Format: common.UnversionedRegistry,
|
||||
})
|
||||
rs.Create(&common.Registry{
|
||||
Name: "application-dm-templates",
|
||||
Type: common.Github,
|
||||
URL: "github.com/kubernetes/application-dm-templates",
|
||||
Format: common.VersionedRegistry,
|
||||
})
|
||||
return rs
|
||||
}
|
||||
|
||||
func (rs *inmemRepositoryService) List() ([]*common.Registry, error) {
|
||||
ret := []*common.Registry{}
|
||||
for _, r := range rs.repositories {
|
||||
ret = append(ret, r)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (rs *inmemRepositoryService) Create(repository *common.Registry) error {
|
||||
rs.repositories[repository.URL] = repository
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rs *inmemRepositoryService) Get(name string) (*common.Registry, error) {
|
||||
return &common.Registry{}, nil
|
||||
}
|
||||
|
||||
func (rs *inmemRepositoryService) Delete(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetByURL returns a registry that handles the types for a given URL.
|
||||
func (rs *inmemRepositoryService) GetByURL(URL string) (*common.Registry, error) {
|
||||
for _, r := range rs.repositories {
|
||||
if strings.HasPrefix(URL, r.URL) {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Failed to find registry for github url: %s", URL)
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testUrlConversionDriver(rp RegistryProvider, tests map[string]TestURLAndError, t *testing.T) {
|
||||
for in, expected := range tests {
|
||||
actual, err := GetDownloadURLs(rp, in)
|
||||
if err != expected.Err {
|
||||
t.Fatalf("failed on: %s : expected error %v but got %v", in, expected.Err, err)
|
||||
}
|
||||
|
||||
if actual[0] != expected.URL {
|
||||
t.Fatalf("failed on: %s : expected %s but got %v", in, expected.URL, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortGithubUrlTemplateMapping(t *testing.T) {
|
||||
githubUrlMaps := map[Type]TestURLAndError{
|
||||
NewTypeOrDie("common", "replicatedservice", "v1"): TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", nil},
|
||||
NewTypeOrDie("storage", "redis", "v1"): TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/storage/redis/v1/redis.jinja", nil},
|
||||
}
|
||||
|
||||
tests := map[string]TestURLAndError{
|
||||
"github.com/kubernetes/application-dm-templates/common/replicatedservice:v1": TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", nil},
|
||||
"github.com/kubernetes/application-dm-templates/storage/redis:v1": TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/storage/redis/v1/redis.jinja", nil},
|
||||
}
|
||||
|
||||
grp := NewTestGithubRegistryProvider("github.com/kubernetes/application-dm-templates", githubUrlMaps)
|
||||
testUrlConversionDriver(NewRegistryProvider(nil, grp), tests, t)
|
||||
}
|
||||
|
||||
func TestShortGithubUrlPackageMapping(t *testing.T) {
|
||||
githubUrlMaps := map[Type]TestURLAndError{
|
||||
NewTypeOrDie("", "mongodb", ""): TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/mongodb/manifests/mongodb.yaml", nil},
|
||||
NewTypeOrDie("", "redis", ""): TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/redis/manifests/redis.yaml", nil},
|
||||
}
|
||||
|
||||
tests := map[string]TestURLAndError{
|
||||
"github.com/helm/charts/mongodb": TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/mongodb/manifests/mongodb.yaml", nil},
|
||||
"github.com/helm/charts/redis": TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/redis/manifests/redis.yaml", nil},
|
||||
}
|
||||
|
||||
grp := NewTestGithubRegistryProvider("github.com/helm/charts", githubUrlMaps)
|
||||
testUrlConversionDriver(NewRegistryProvider(nil, grp), tests, t)
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SemVer struct {
|
||||
Major uint
|
||||
Minor uint
|
||||
Patch uint
|
||||
}
|
||||
|
||||
func ParseSemVer(version string) (SemVer, error) {
|
||||
var err error
|
||||
major, minor, patch := uint64(0), uint64(0), uint64(0)
|
||||
if len(version) > 0 {
|
||||
parts := strings.SplitN(version, ".", 3)
|
||||
if len(parts) > 3 {
|
||||
return SemVer{}, fmt.Errorf("invalid semantic version: %s", version)
|
||||
}
|
||||
|
||||
if len(parts) < 1 {
|
||||
return SemVer{}, fmt.Errorf("invalid semantic version: %s", version)
|
||||
}
|
||||
|
||||
if parts[0] != "0" {
|
||||
major, err = strconv.ParseUint(parts[0], 10, 0)
|
||||
if err != nil {
|
||||
return SemVer{}, fmt.Errorf("invalid semantic version: %s", version)
|
||||
}
|
||||
}
|
||||
|
||||
if len(parts) > 1 {
|
||||
if parts[1] != "0" {
|
||||
minor, err = strconv.ParseUint(parts[1], 10, 0)
|
||||
if err != nil {
|
||||
return SemVer{}, fmt.Errorf("invalid semantic version: %s", version)
|
||||
}
|
||||
}
|
||||
|
||||
if len(parts) > 2 {
|
||||
if parts[2] != "0" {
|
||||
patch, err = strconv.ParseUint(parts[2], 10, 0)
|
||||
if err != nil {
|
||||
return SemVer{}, fmt.Errorf("invalid semantic version: %s", version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SemVer{Major: uint(major), Minor: uint(minor), Patch: uint(patch)}, nil
|
||||
}
|
||||
|
||||
func (s SemVer) IsZero() bool {
|
||||
return s.Major == 0 && s.Minor == 0 && s.Patch == 0
|
||||
}
|
||||
|
||||
// SemVer conforms to the Stringer interface.
|
||||
func (s SemVer) String() string {
|
||||
result := strconv.Itoa(int(s.Major))
|
||||
if s.Minor != 0 || s.Patch != 0 {
|
||||
result = result + "." + strconv.Itoa(int(s.Minor))
|
||||
}
|
||||
|
||||
if s.Patch != 0 {
|
||||
result = result + "." + strconv.Itoa(int(s.Patch))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseInvalidVersionFails(t *testing.T) {
|
||||
for _, test := range []string{
|
||||
".",
|
||||
"..",
|
||||
"...",
|
||||
"1.2.3.4",
|
||||
"notAUnit",
|
||||
"1.notAUint",
|
||||
"1.1.notAUint",
|
||||
"-1",
|
||||
"1.-1",
|
||||
"1.1.-1",
|
||||
"1,1",
|
||||
"1.1,1",
|
||||
} {
|
||||
_, err := ParseSemVer(test)
|
||||
if err == nil {
|
||||
t.Errorf("Invalid version parsed successfully: %s\n", test)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseValidVersionSucceeds(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
String string
|
||||
Version SemVer
|
||||
}{
|
||||
{"", SemVer{0, 0, 0}},
|
||||
{"0", SemVer{0, 0, 0}},
|
||||
{"0.0", SemVer{0, 0, 0}},
|
||||
{"0.0.0", SemVer{0, 0, 0}},
|
||||
{"1", SemVer{1, 0, 0}},
|
||||
{"1.0", SemVer{1, 0, 0}},
|
||||
{"1.0.0", SemVer{1, 0, 0}},
|
||||
{"1.1", SemVer{1, 1, 0}},
|
||||
{"1.1.0", SemVer{1, 1, 0}},
|
||||
{"1.1.1", SemVer{1, 1, 1}},
|
||||
} {
|
||||
result, err := ParseSemVer(test.String)
|
||||
if err != nil {
|
||||
t.Errorf("Valid version %s did not parse successfully\n", test.String)
|
||||
}
|
||||
|
||||
if result.Major != test.Version.Major ||
|
||||
result.Minor != test.Version.Minor ||
|
||||
result.Patch != test.Version.Patch {
|
||||
t.Errorf("Valid version %s did not parse correctly: %s\n", test.String, test.Version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertSemVerToStringSucceeds(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
String string
|
||||
Version SemVer
|
||||
}{
|
||||
{"0", SemVer{0, 0, 0}},
|
||||
{"0.1", SemVer{0, 1, 0}},
|
||||
{"0.0.1", SemVer{0, 0, 1}},
|
||||
{"1", SemVer{1, 0, 0}},
|
||||
{"1.1", SemVer{1, 1, 0}},
|
||||
{"1.1.1", SemVer{1, 1, 1}},
|
||||
} {
|
||||
result := test.Version.String()
|
||||
if result != test.String {
|
||||
t.Errorf("Valid version %s did not format correctly: %s\n", test.Version, test.String)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
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
|
||||
|
||||
// TODO(jackgr): Mock github repository service to test package and template registry implementations.
|
||||
|
||||
import (
|
||||
"github.com/kubernetes/deployment-manager/common"
|
||||
"github.com/kubernetes/deployment-manager/util"
|
||||
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type TestURLAndError struct {
|
||||
URL string
|
||||
Err error
|
||||
}
|
||||
|
||||
type testGithubRegistryProvider struct {
|
||||
shortURL string
|
||||
responses map[Type]TestURLAndError
|
||||
}
|
||||
|
||||
type testGithubRegistry struct {
|
||||
githubRegistry
|
||||
responses map[Type]TestURLAndError
|
||||
}
|
||||
|
||||
func NewTestGithubRegistryProvider(shortURL string, responses map[Type]TestURLAndError) GithubRegistryProvider {
|
||||
return testGithubRegistryProvider{
|
||||
shortURL: util.TrimURLScheme(shortURL),
|
||||
responses: responses,
|
||||
}
|
||||
}
|
||||
|
||||
func (tgrp testGithubRegistryProvider) GetGithubRegistry(cr common.Registry) (GithubRegistry, error) {
|
||||
trimmed := util.TrimURLScheme(cr.URL)
|
||||
if strings.HasPrefix(trimmed, tgrp.shortURL) {
|
||||
ghr, err := newGithubRegistry(cr.Name, trimmed, cr.Format, nil)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot create a github registry: %s", err))
|
||||
}
|
||||
|
||||
return &testGithubRegistry{
|
||||
githubRegistry: *ghr,
|
||||
responses: tgrp.responses,
|
||||
}, nil
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("unknown registry: %v", cr))
|
||||
}
|
||||
|
||||
func (tgr testGithubRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) {
|
||||
panic(fmt.Errorf("ListTypes should not be called in the test"))
|
||||
}
|
||||
|
||||
func (tgr testGithubRegistry) GetDownloadURLs(t Type) ([]*url.URL, error) {
|
||||
result := tgr.responses[t]
|
||||
URL, err := url.Parse(result.URL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return []*url.URL{URL}, result.Err
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/kubernetes/deployment-manager/common"
|
||||
)
|
||||
|
||||
var TemplateRegistryMatcher = regexp.MustCompile("github.com/(.*)/(.*)/(.*)/(.*):(.*)")
|
||||
|
||||
// RE for Registry that does not support versions and can have multiple files without imports.
|
||||
var PackageRegistryMatcher = regexp.MustCompile("github.com/(.*)/(.*)/(.*)")
|
||||
|
||||
// IsTemplate returns whether a given type is a template.
|
||||
func IsTemplate(t string, imports []*common.ImportFile) bool {
|
||||
for _, imp := range imports {
|
||||
if imp.Name == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
Loading…
Reference in new issue