diff --git a/cmd/dm/dm.go b/cmd/dm/dm.go index 2a28b8031..0eee56a8d 100644 --- a/cmd/dm/dm.go +++ b/cmd/dm/dm.go @@ -20,6 +20,7 @@ import ( "github.com/ghodss/yaml" "github.com/kubernetes/helm/pkg/common" + "github.com/kubernetes/helm/pkg/repo" "github.com/kubernetes/helm/pkg/util" "archive/tar" @@ -90,15 +91,15 @@ var usage = func() { os.Exit(0) } -func getCredential() *common.RegistryCredential { +func getCredential() *repo.Credential { *apitoken = strings.TrimSpace(*apitoken) if *apitoken == "" { *apitoken = strings.TrimSpace(os.Getenv("GITHUB_API_TOKEN")) } if *apitoken != "" { - return &common.RegistryCredential{ - APIToken: common.APITokenCredential(*apitoken), + return &repo.Credential{ + APIToken: repo.APITokenCredential(*apitoken), } } @@ -113,8 +114,8 @@ func getCredential() *common.RegistryCredential { *password = strings.TrimSpace(os.Getenv("GITHUB_PASSWORD")) } - return &common.RegistryCredential{ - BasicAuth: common.BasicAuthCredential{ + return &repo.Credential{ + BasicAuth: repo.BasicAuthCredential{ Username: *username, Password: *password, }, @@ -126,8 +127,8 @@ func getCredential() *common.RegistryCredential { if err != nil { log.Fatalf("Unable to read service account file: %v", err) } - return &common.RegistryCredential{ - ServiceAccount: common.JWTTokenCredential(string(b)), + return &repo.Credential{ + ServiceAccount: repo.JWTTokenCredential(string(b)), } } return nil diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go index fc068285a..4a3281745 100644 --- a/pkg/chart/chart.go +++ b/pkg/chart/chart.go @@ -427,20 +427,20 @@ func (c *Chart) loadMember(filename string) (*Member, error) { return result, nil } -// ChartContent is abstraction for the contents of a chart. -type ChartContent struct { +// Content is abstraction for the contents of a chart. +type Content struct { Chartfile *Chartfile `json:"chartfile"` Members []*Member `json:"members"` } -// loadContent loads contents of a chart directory into ChartContent -func (c *Chart) loadContent() (*ChartContent, error) { +// LoadContent loads contents of a chart directory into Content +func (c *Chart) LoadContent() (*Content, error) { ms, err := c.loadDirectory(c.Dir()) if err != nil { return nil, err } - cc := &ChartContent{ + cc := &Content{ Chartfile: c.Chartfile(), Members: ms, } diff --git a/pkg/common/types.go b/pkg/common/types.go index 0d17cc092..ed44382e5 100644 --- a/pkg/common/types.go +++ b/pkg/common/types.go @@ -21,17 +21,6 @@ import ( "time" ) -// SchemaImport represents an import as declared in a schema file. -type SchemaImport struct { - Path string `json:"path"` - Name string `json:"name"` -} - -// Schema is a partial DM schema. We only need access to the imports object at this level. -type Schema struct { - Imports []SchemaImport `json:"imports"` -} - // Deployment defines a deployment that describes // the creation, modification and/or deletion of a set of resources. type Deployment struct { @@ -76,17 +65,6 @@ func (s DeploymentStatus) String() string { return string(s) } -// LayoutResource defines the structure of resources in the manifest layout. -type LayoutResource struct { - Resource - Layout -} - -// Layout defines the structure of a layout as returned from expansion. -type Layout struct { - Resources []*LayoutResource `json:"resources,omitempty"` -} - // Manifest contains the input configuration for a deployment, the fully // expanded configuration, and the layout structure of the manifest. // @@ -103,21 +81,16 @@ type CreateDeploymentRequest struct { ChartInvocation *Resource `json:"chart_invocation"` } -// ExpansionRequest defines the API to expander. -type ExpansionRequest struct { - ChartInvocation *Resource `json:"chart_invocation"` - Chart *chart.ChartContent `json:"chart"` -} - -// ExpansionResponse defines the API to expander. -type ExpansionResponse struct { - Resources []interface{} `json:"resources"` +// ChartInstance defines the metadata for an instantiation of a chart. +type ChartInstance struct { + Name string `json:"name"` // instance name + Type string `json:"type"` // instance type + Deployment string `json:"deployment"` // deployment name + Manifest string `json:"manifest"` // manifest name + Path string `json:"path"` // JSON path within manifest } -// Expander abstracts interactions with the expander and deployer services. -type Expander interface { - ExpandChart(request *ExpansionRequest) (*ExpansionResponse, error) -} +// TODO: Remove the following section when the refactoring of templates is complete. // Template describes a set of resources to be deployed. // Manager expands a Template into a Configuration, which @@ -135,6 +108,44 @@ type ImportFile struct { Content string `json:"content"` } +// SchemaImport represents an import as declared in a schema file. +type SchemaImport struct { + Path string `json:"path"` + Name string `json:"name"` +} + +// Schema is a partial DM schema. We only need access to the imports object at this level. +type Schema struct { + Imports []SchemaImport `json:"imports"` +} + +// LayoutResource defines the structure of resources in the manifest layout. +type LayoutResource struct { + Resource + Layout +} + +// Layout defines the structure of a layout as returned from expansion. +type Layout struct { + Resources []*LayoutResource `json:"resources,omitempty"` +} + +// ExpansionRequest defines the API to expander. +type ExpansionRequest struct { + ChartInvocation *Resource `json:"chart_invocation"` + Chart *chart.Content `json:"chart"` +} + +// ExpansionResponse defines the API to expander. +type ExpansionResponse struct { + Resources []interface{} `json:"resources"` +} + +// Expander abstracts interactions with the expander and deployer services. +type Expander interface { + ExpandChart(request *ExpansionRequest) (*ExpansionResponse, error) +} + // Configuration describes a set of resources in a form // that can be instantiated. type Configuration struct { @@ -169,102 +180,3 @@ type Resource struct { Properties map[string]interface{} `json:"properties,omitempty"` State *ResourceState `json:"state,omitempty"` } - -// ChartInstance defines the metadata for an instantiation of a template type -// in a deployment. -type ChartInstance struct { - Name string `json:"name"` // instance name - Type string `json:"type"` // instance type - Deployment string `json:"deployment"` // deployment name - Manifest string `json:"manifest"` // manifest name - Path string `json:"path"` // JSON path within manifest -} - -// TODO: Remove the remainder of this file when the refactoring of pkg/registry is complete. - -// BasicAuthCredential holds a username and password. -type BasicAuthCredential struct { - Username string `json:"username"` - Password string `json:"password"` -} - -// APITokenCredential defines an API token. -type APITokenCredential string - -// JWTTokenCredential defines a JWT token. -type JWTTokenCredential string - -// RegistryCredential holds a credential used to access a registry. -type RegistryCredential struct { - APIToken APITokenCredential `json:"apitoken,omitempty"` - BasicAuth BasicAuthCredential `json:"basicauth,omitempty"` - ServiceAccount JWTTokenCredential `json:"serviceaccount,omitempty"` -} - -// Registry describes a template registry -type Registry struct { - Name string `json:"name,omitempty"` // Friendly name for the registry - Type RegistryType `json:"type,omitempty"` // Technology implementing the registry - URL string `json:"url,omitempty"` // URL to the root of the registry - Format RegistryFormat `json:"format,omitempty"` // Format of the registry - CredentialName string `json:"credentialname,omitempty"` // Name of the credential to use -} - -// RegistryType defines the technology that implements a registry. -type RegistryType string - -// Constants that identify the supported registry types. -const ( - GithubRegistryType RegistryType = "github" - GCSRegistryType RegistryType = "gcs" -) - -// RegistryFormat is a semi-colon delimited string that describes the format -// of a registry. -type RegistryFormat string - -const ( - // Versioning. - - // VersionedRegistry identifies a versioned registry, where types appear under versions. - VersionedRegistry RegistryFormat = "versioned" - // UnversionedRegistry identifies an unversioned registry, where types appear under their names. - UnversionedRegistry RegistryFormat = "unversioned" - - // Organization. - - // CollectionRegistry identfies a collection registry, where types are grouped into collections. - CollectionRegistry RegistryFormat = "collection" - // OneLevelRegistry identifies a one level registry, where all types appear at the top level. - OneLevelRegistry RegistryFormat = "onelevel" -) - -// RegistryService maintains a set of registries that defines the scope of all -// registry based operations, such as search and type resolution. -type RegistryService interface { - // List all the registries - List() ([]*Registry, error) - // Create a new registry - Create(registry *Registry) error - // Get a registry - Get(name string) (*Registry, error) - // Get a registry with credential. - GetRegistry(name string) (*Registry, error) - // Delete a registry - Delete(name string) error - // Find a registry that backs the given URL - GetByURL(URL string) (*Registry, error) - // GetRegistryByURL returns a registry that handles the types for a given URL. - GetRegistryByURL(URL string) (*Registry, error) -} - -// CredentialProvider provides credentials for registries. -type CredentialProvider interface { - // Set the credential for a registry. - // May not be supported by some registry services. - SetCredential(name string, credential *RegistryCredential) error - - // GetCredential returns the specified credential or nil if there's no credential. - // Error is non-nil if fetching the credential failed. - GetCredential(name string) (*RegistryCredential, error) -} diff --git a/pkg/expander/types.go b/pkg/expander/types.go new file mode 100644 index 000000000..6ae2e09e6 --- /dev/null +++ b/pkg/expander/types.go @@ -0,0 +1,94 @@ +/* +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 expander + +import ( + "github.com/kubernetes/helm/pkg/chart" +) + +// SchemaImport represents an import as declared in a schema file. +type SchemaImport struct { + Path string `json:"path"` + Name string `json:"name"` +} + +// Schema is a partial DM schema. We only need access to the imports object at this level. +type Schema struct { + Imports []SchemaImport `json:"imports"` +} + +// LayoutResource defines the structure of resources in the manifest layout. +type LayoutResource struct { + Resource + Layout +} + +// Layout defines the structure of a layout as returned from expansion. +type Layout struct { + Resources []*LayoutResource `json:"resources,omitempty"` +} + +// ExpansionRequest defines the API to expander. +type ExpansionRequest struct { + ChartInvocation *Resource `json:"chart_invocation"` + Chart *chart.Content `json:"chart"` +} + +// ExpansionResponse defines the API to expander. +type ExpansionResponse struct { + Resources []interface{} `json:"resources"` +} + +// Expander abstracts interactions with the expander and deployer services. +type Expander interface { + ExpandChart(request *ExpansionRequest) (*ExpansionResponse, error) +} + +// Configuration describes a set of resources in a form +// that can be instantiated. +type Configuration struct { + Resources []*Resource `json:"resources"` +} + +// ResourceStatus is an enumeration type for the status of a resource. +type ResourceStatus string + +// These constants implement the resourceStatus enumeration type. +const ( + Created ResourceStatus = "Created" + Failed ResourceStatus = "Failed" + Aborted ResourceStatus = "Aborted" +) + +// ResourceState describes the state of a resource. +// Status is set during resource creation and is a terminal state. +type ResourceState struct { + Status ResourceStatus `json:"status,omitempty"` + SelfLink string `json:"selflink,omitempty"` + Errors []string `json:"errors,omitempty"` +} + +// Resource describes a resource in a configuration. A resource has +// a name, a type and a set of properties. The name and type are used +// to identify the resource in Kubernetes. The properties are passed +// to Kubernetes as the resource configuration. +type Resource struct { + Name string `json:"name"` + Type string `json:"type"` + Properties map[string]interface{} `json:"properties,omitempty"` + State *ResourceState `json:"state,omitempty"` +} diff --git a/pkg/registry/filebased_credential_provider.go b/pkg/registry/filebased_credential_provider.go deleted file mode 100644 index 3c42fcbcc..000000000 --- a/pkg/registry/filebased_credential_provider.go +++ /dev/null @@ -1,79 +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" - "io/ioutil" - "log" - - "github.com/ghodss/yaml" - "github.com/kubernetes/helm/pkg/common" -) - -// FilebasedCredentialProvider provides credentials for registries. -type FilebasedCredentialProvider struct { - // Actual backing store - backingCredentialProvider common.CredentialProvider -} - -// NamedRegistryCredential associates a name with a RegistryCredential. -type NamedRegistryCredential struct { - Name string `json:"name,omitempty"` - common.RegistryCredential -} - -// NewFilebasedCredentialProvider creates a file based credential provider. -func NewFilebasedCredentialProvider(filename string) (common.CredentialProvider, error) { - icp := NewInmemCredentialProvider() - c, err := readCredentialsFile(filename) - if err != nil { - return &FilebasedCredentialProvider{}, err - } - for _, nc := range c { - log.Printf("Adding credential %s", nc.Name) - icp.SetCredential(nc.Name, &nc.RegistryCredential) - } - - return &FilebasedCredentialProvider{icp}, nil -} - -func readCredentialsFile(filename string) ([]NamedRegistryCredential, error) { - bytes, err := ioutil.ReadFile(filename) - if err != nil { - return []NamedRegistryCredential{}, err - } - return parseCredentials(bytes) -} - -func parseCredentials(bytes []byte) ([]NamedRegistryCredential, error) { - r := []NamedRegistryCredential{} - if err := yaml.Unmarshal(bytes, &r); err != nil { - return []NamedRegistryCredential{}, fmt.Errorf("cannot unmarshal credentials file (%#v)", err) - } - return r, nil -} - -// GetCredential returns a credential by name. -func (fcp *FilebasedCredentialProvider) GetCredential(name string) (*common.RegistryCredential, error) { - return fcp.backingCredentialProvider.GetCredential(name) -} - -// SetCredential sets a credential by name. -func (fcp *FilebasedCredentialProvider) SetCredential(name string, credential *common.RegistryCredential) error { - return fmt.Errorf("SetCredential operation not supported with FilebasedCredentialProvider") -} diff --git a/pkg/registry/filebased_credential_provider_test.go b/pkg/registry/filebased_credential_provider_test.go deleted file mode 100644 index 4cc1a2edd..000000000 --- a/pkg/registry/filebased_credential_provider_test.go +++ /dev/null @@ -1,60 +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 ( - "testing" - - "github.com/kubernetes/helm/pkg/common" -) - -var filename = "./test/test_credentials_file.yaml" - -type filebasedTestCase struct { - name string - exp *common.RegistryCredential - expErr error -} - -func TestNotExistFilebased(t *testing.T) { - cp, err := NewFilebasedCredentialProvider(filename) - if err != nil { - t.Fatalf("Failed to create a new FilebasedCredentialProvider %s : %v", filename, err) - } - tc := &testCase{"nonexistent", nil, createMissingError("nonexistent")} - testGetCredential(t, cp, tc) -} - -func TestGetApiTokenFilebased(t *testing.T) { - cp, err := NewFilebasedCredentialProvider(filename) - if err != nil { - t.Fatalf("Failed to create a new FilebasedCredentialProvider %s : %v", filename, err) - } - tc := &testCase{"test1", &common.RegistryCredential{APIToken: "token"}, nil} - testGetCredential(t, cp, tc) -} - -func TestSetAndGetBasicAuthFilebased(t *testing.T) { - cp, err := NewFilebasedCredentialProvider(filename) - if err != nil { - t.Fatalf("Failed to create a new FilebasedCredentialProvider %s : %v", filename, err) - } - tc := &testCase{"test2", - &common.RegistryCredential{ - BasicAuth: common.BasicAuthCredential{Username: "user", Password: "password"}}, nil} - testGetCredential(t, cp, tc) -} diff --git a/pkg/registry/gcs_registry.go b/pkg/registry/gcs_registry.go deleted file mode 100644 index edd40907a..000000000 --- a/pkg/registry/gcs_registry.go +++ /dev/null @@ -1,167 +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 ( - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" - - // "golang.org/x/net/context" - // "golang.org/x/oauth2/google" - storage "google.golang.org/api/storage/v1" - - "fmt" - "log" - "net/http" - "net/url" - "regexp" -) - -// GCSRegistry implements the ObbectStorageRegistry interface and implements a -// Deployment Manager templates registry. -// -// A registry root must be a directory that contains all the available charts, -// one or two files per template. -// name-version.tgz -// name-version.prov -type GCSRegistry struct { - name string - shortURL string - bucket string - format common.RegistryFormat - credentialName string - - httpClient *http.Client - service *storage.Service -} - -// RE for GCS storage - -// ChartFormatMatcher matches the chart name format -var ChartFormatMatcher = regexp.MustCompile("(.*)-(.*).tgz") - -// URLFormatMatcher matches the GCS URL format (gs:). -var URLFormatMatcher = regexp.MustCompile("gs://(.*)") - -// NewGCSRegistry creates a GCS registry. -func NewGCSRegistry(name, shortURL string, httpClient *http.Client, gcsService *storage.Service) (*GCSRegistry, error) { - format := fmt.Sprintf("%s;%s", common.VersionedRegistry, common.OneLevelRegistry) - trimmed := util.TrimURLScheme(shortURL) - m := URLFormatMatcher.FindStringSubmatch(shortURL) - if len(m) != 2 { - return nil, fmt.Errorf("URL must be of the form gs:// was: %s", shortURL) - } - - return &GCSRegistry{ - name: name, - shortURL: trimmed, - format: common.RegistryFormat(format), - httpClient: httpClient, - service: gcsService, - bucket: m[1], - }, - nil -} - -// GetRegistryName returns the name of the registry. -func (g GCSRegistry) GetRegistryName() string { - return g.name -} - -// GetBucket returns the registry bucket. -func (g GCSRegistry) GetBucket() string { - return g.bucket -} - -// GetRegistryType returns the registry type. -func (g GCSRegistry) GetRegistryType() common.RegistryType { - return common.GCSRegistryType -} - -// 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 GCSRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) { - // List all files in the bucket/prefix that contain the - types := []Type{} - - // List all objects in a bucket using pagination - pageToken := "" - for { - call := g.service.Objects.List(g.bucket) - call.Delimiter("/") - if pageToken != "" { - call = call.PageToken(pageToken) - } - res, err := call.Do() - if err != nil { - return []Type{}, err - } - for _, object := range res.Items { - // Charts should be named bucket/chart-X.Y.Z.tgz, so tease apart the version here - m := ChartFormatMatcher.FindStringSubmatch(object.Name) - if len(m) != 3 { - continue - } - - t, err := NewType("", m[1], m[2]) - if err != nil { - return []Type{}, fmt.Errorf("can't create a type type at path %#v", err) - } - types = append(types, t) - } - if pageToken = res.NextPageToken; pageToken == "" { - break - } - } - return types, nil -} - -// GetRegistryFormat returns the registry format. -func (g GCSRegistry) GetRegistryFormat() common.RegistryFormat { - return common.CollectionRegistry -} - -// GetRegistryShortURL returns the short URL for the registry. -func (g GCSRegistry) GetRegistryShortURL() string { - return g.shortURL -} - -// GetDownloadURLs fetches the download URLs for a given Chart -func (g GCSRegistry) GetDownloadURLs(t Type) ([]*url.URL, error) { - call := g.service.Objects.List(g.bucket) - call.Delimiter("/") - call.Prefix(t.String()) - res, err := call.Do() - ret := []*url.URL{} - if err != nil { - return ret, err - } - for _, object := range res.Items { - log.Printf("Found: %s", object.Name) - u, err := url.Parse(object.MediaLink) - if err != nil { - return nil, fmt.Errorf("cannot parse URL from %s: %s", object.MediaLink, err) - } - ret = append(ret, u) - } - return ret, err -} - -// Do performs an HTTP operation on the receiver's httpClient. -func (g GCSRegistry) Do(req *http.Request) (resp *http.Response, err error) { - return g.httpClient.Do(req) -} diff --git a/pkg/registry/github_package_registry.go b/pkg/registry/github_package_registry.go deleted file mode 100644 index e55144d1f..000000000 --- a/pkg/registry/github_package_registry.go +++ /dev/null @@ -1,159 +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 ( - "github.com/google/go-github/github" - "github.com/kubernetes/helm/pkg/common" - - "fmt" - "log" - "net/http" - "net/url" - "regexp" - "strings" -) - -// GithubPackageRegistry implements the Registry interface that talks to github and -// expects packages in helm format without versioning and no collection in the path. -// Format of the directory for a type is like so: -// package/ -// Chart.yaml -// manifests/ -// foo.yaml -// bar.yaml -// ... -type GithubPackageRegistry struct { - githubRegistry -} - -// NewGithubPackageRegistry creates a GithubPackageRegistry. -func NewGithubPackageRegistry(name, shortURL string, service GithubRepositoryService, httpClient *http.Client, client *github.Client) (*GithubPackageRegistry, error) { - format := fmt.Sprintf("%s;%s", common.UnversionedRegistry, common.OneLevelRegistry) - if service == nil { - if client == nil { - service = github.NewClient(nil).Repositories - } else { - service = client.Repositories - } - } - - gr, err := newGithubRegistry(name, shortURL, common.RegistryFormat(format), httpClient, service) - if err != nil { - return nil, err - } - - return &GithubPackageRegistry{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 GithubPackageRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) { - // Just list all the types at the top level. - types, err := g.getDirs("") - if err != nil { - log.Printf("Failed to list templates: %v", err) - return nil, err - } - - var retTypes []Type - for _, t := range types { - // Check to see if there's a Chart.yaml file in the directory - _, dc, _, err := g.service.GetContents(g.owner, g.repository, t, nil) - if err != nil { - log.Printf("Failed to list package files at path: %s: %v", t, err) - return nil, err - } - for _, f := range dc { - if *f.Type == "file" && *f.Name == "Chart.yaml" { - retTypes = append(retTypes, Type{Name: t}) - } - } - } - - 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. -func (g GithubPackageRegistry) 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 { - log.Printf("Failed to list package files at path: %s: %v", path, err) - return nil, err - } - - downloadURLs := []*url.URL{} - for _, f := range dc { - if *f.Type == "file" { - if strings.HasSuffix(*f.Name, ".yaml") { - u, err := url.Parse(*f.DownloadURL) - if err != nil { - return nil, fmt.Errorf("cannot parse URL from %s: %s", *f.DownloadURL, err) - } - - downloadURLs = append(downloadURLs, u) - } - } - } - return downloadURLs, nil -} - -func (g GithubPackageRegistry) getDirs(dir string) ([]string, error) { - _, dc, _, err := g.service.GetContents(g.owner, g.repository, dir, nil) - if err != nil { - log.Printf("Failed to get contents at path: %s: %v", dir, err) - return nil, err - } - - var dirs []string - for _, entry := range dc { - if *entry.Type == "dir" { - dirs = append(dirs, *entry.Name) - } - } - - return dirs, nil -} - -// MakeRepositoryPath constructs a github path to a given type based on a repository, and type name. -// The returned repository path will be of the form: -// Type.Name/manifests -func (g GithubPackageRegistry) MakeRepositoryPath(t Type) (string, error) { - // Construct the return path - return t.Name + "/manifests", nil -} - -// Do performs an HTTP operation on the receiver's httpClient. -func (g GithubPackageRegistry) Do(req *http.Request) (resp *http.Response, err error) { - return g.httpClient.Do(req) -} diff --git a/pkg/registry/github_registry.go b/pkg/registry/github_registry.go deleted file mode 100644 index 844ca11ea..000000000 --- a/pkg/registry/github_registry.go +++ /dev/null @@ -1,132 +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 ( - "github.com/google/go-github/github" - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" - - "fmt" - "net/http" - "strings" -) - -// githubRegistry is the base class for the Registry interface and talks to github. Actual implementations are -// in GithubPackageRegistry and GithubTemplateRegistry. -// The registry short URL and format determine how types are laid out in the -// registry. -type githubRegistry struct { - name string - shortURL string - owner string - repository string - path string - format common.RegistryFormat - credentialName string - service GithubRepositoryService - httpClient *http.Client -} - -// GithubRepositoryService defines the interface that's defined in github.com/go-github/repos_contents.go GetContents method. -type GithubRepositoryService interface { - GetContents( - owner, repo, path string, - opt *github.RepositoryContentGetOptions, - ) ( - fileContent *github.RepositoryContent, - directoryContent []*github.RepositoryContent, - resp *github.Response, - err error, - ) -} - -// newGithubRegistry creates a githubRegistry. -func newGithubRegistry(name, shortURL string, format common.RegistryFormat, httpClient *http.Client, service GithubRepositoryService) (*githubRegistry, error) { - trimmed := util.TrimURLScheme(shortURL) - owner, repository, path, err := parseGithubShortURL(trimmed) - if err != nil { - return nil, fmt.Errorf("cannot create Github template registry %s: %s", name, err) - } - - return &githubRegistry{ - name: name, - shortURL: trimmed, - owner: owner, - repository: repository, - path: path, - format: format, - service: service, - httpClient: httpClient, - }, nil -} - -func parseGithubShortURL(shortURL string) (string, string, string, error) { - if !strings.HasPrefix(shortURL, "github.com/") { - return "", "", "", fmt.Errorf("invalid Github short URL: %s", shortURL) - } - - tPath := strings.TrimPrefix(shortURL, "github.com/") - parts := strings.Split(tPath, "/") - - // Handle the case where there's no path after owner and repository. - if len(parts) == 2 { - return parts[0], parts[1], "", nil - } - - // Handle the case where there's a path after owner and repository. - if len(parts) == 3 { - return parts[0], parts[1], parts[2], nil - } - - return "", "", "", fmt.Errorf("invalid Github short URL: %s", shortURL) -} - -// GetRegistryName returns the name of this registry -func (g githubRegistry) GetRegistryName() string { - return g.name -} - -// GetRegistryType returns the type of this registry. -func (g githubRegistry) GetRegistryType() common.RegistryType { - return common.GithubRegistryType -} - -// GetRegistryShortURL returns the short URL for this registry. -func (g githubRegistry) GetRegistryShortURL() string { - return g.shortURL -} - -// GetRegistryFormat returns the format of this registry. -func (g githubRegistry) GetRegistryFormat() common.RegistryFormat { - return g.format -} - -// GetRegistryOwner returns the owner name for this registry -func (g githubRegistry) GetRegistryOwner() string { - return g.owner -} - -// GetRegistryRepository returns the repository name for this registry. -func (g githubRegistry) GetRegistryRepository() string { - return g.repository -} - -// GetRegistryName returns the name of this registry -func (g githubRegistry) GetRegistryPath() string { - return g.path -} diff --git a/pkg/registry/github_template_registry.go b/pkg/registry/github_template_registry.go deleted file mode 100644 index e7b7f7c7c..000000000 --- a/pkg/registry/github_template_registry.go +++ /dev/null @@ -1,220 +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 ( - "github.com/google/go-github/github" - "github.com/kubernetes/helm/pkg/common" - - "fmt" - "log" - "net/http" - "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 GithubRepositoryService, httpClient *http.Client, client *github.Client) (*GithubTemplateRegistry, error) { - format := fmt.Sprintf("%s;%s", common.VersionedRegistry, common.CollectionRegistry) - if service == nil { - service = client.Repositories - } - - gr, err := newGithubRegistry(name, shortURL, common.RegistryFormat(format), httpClient, 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 -} - -// Do performs an HTTP operation on the receiver's httpClient. -func (g GithubTemplateRegistry) Do(req *http.Request) (resp *http.Response, err error) { - return g.httpClient.Do(req) -} diff --git a/pkg/registry/inmem_credential_provider.go b/pkg/registry/inmem_credential_provider.go deleted file mode 100644 index e1004c08a..000000000 --- a/pkg/registry/inmem_credential_provider.go +++ /dev/null @@ -1,47 +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 ( - "github.com/kubernetes/helm/pkg/common" - - "fmt" -) - -// InmemCredentialProvider is a memory based credential provider. -type InmemCredentialProvider struct { - credentials map[string]*common.RegistryCredential -} - -// NewInmemCredentialProvider creates a new memory based credential provider. -func NewInmemCredentialProvider() common.CredentialProvider { - return &InmemCredentialProvider{credentials: make(map[string]*common.RegistryCredential)} -} - -// GetCredential returns a credential by name. -func (fcp *InmemCredentialProvider) GetCredential(name string) (*common.RegistryCredential, error) { - if val, ok := fcp.credentials[name]; ok { - return val, nil - } - return nil, fmt.Errorf("no such credential : %s", name) -} - -// SetCredential sets a credential by name. -func (fcp *InmemCredentialProvider) SetCredential(name string, credential *common.RegistryCredential) error { - fcp.credentials[name] = &common.RegistryCredential{APIToken: credential.APIToken, BasicAuth: credential.BasicAuth, ServiceAccount: credential.ServiceAccount} - return nil -} diff --git a/pkg/registry/inmem_credential_provider_test.go b/pkg/registry/inmem_credential_provider_test.go deleted file mode 100644 index ecbbeddae..000000000 --- a/pkg/registry/inmem_credential_provider_test.go +++ /dev/null @@ -1,73 +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" - "reflect" - "testing" - - "github.com/kubernetes/helm/pkg/common" -) - -type testCase struct { - name string - exp *common.RegistryCredential - expErr error -} - -func createMissingError(name string) error { - return fmt.Errorf("no such credential : %s", name) -} - -func testGetCredential(t *testing.T, cp common.CredentialProvider, tc *testCase) { - actual, actualErr := cp.GetCredential(tc.name) - if !reflect.DeepEqual(actual, tc.exp) { - t.Fatalf("failed on: %s : expected %#v but got %#v", tc.name, tc.exp, actual) - } - if !reflect.DeepEqual(actualErr, tc.expErr) { - t.Fatalf("failed on: %s : expected error %#v but got %#v", tc.name, tc.expErr, actualErr) - } -} - -func verifySetAndGetCredential(t *testing.T, cp common.CredentialProvider, tc *testCase) { - err := cp.SetCredential(tc.name, tc.exp) - if err != nil { - t.Fatalf("Failed to SetCredential on %s : %v", tc.name, err) - } - testGetCredential(t, cp, tc) -} - -func TestNotExist(t *testing.T) { - cp := NewInmemCredentialProvider() - tc := &testCase{"nonexistent", nil, createMissingError("nonexistent")} - testGetCredential(t, cp, tc) -} - -func TestSetAndGetApiToken(t *testing.T) { - cp := NewInmemCredentialProvider() - tc := &testCase{"testcredential", &common.RegistryCredential{APIToken: "some token here"}, nil} - verifySetAndGetCredential(t, cp, tc) -} - -func TestSetAndGetBasicAuth(t *testing.T) { - cp := NewInmemCredentialProvider() - tc := &testCase{"testcredential", - &common.RegistryCredential{ - BasicAuth: common.BasicAuthCredential{Username: "user", Password: "pass"}}, nil} - verifySetAndGetCredential(t, cp, tc) -} diff --git a/pkg/registry/inmem_registry_service.go b/pkg/registry/inmem_registry_service.go deleted file mode 100644 index cd3c92242..000000000 --- a/pkg/registry/inmem_registry_service.go +++ /dev/null @@ -1,127 +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 ( - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" - - "fmt" - "strings" -) - -type inmemRegistryService struct { - registries map[string]*common.Registry -} - -// NewInmemRegistryService returns a new memory based registry service. -func NewInmemRegistryService() common.RegistryService { - rs := &inmemRegistryService{ - registries: make(map[string]*common.Registry), - } - - 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), - CredentialName: "default", - }) - - 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), - CredentialName: "default", - }) - - 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) - } - - return ret, nil -} - -// Create creates a registry. -func (rs *inmemRegistryService) Create(registry *common.Registry) error { - rs.registries[registry.Name] = 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, nil -} - -// GetRegistry returns a registry with a given name. -func (rs *inmemRegistryService) GetRegistry(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, nil -} - -// Delete deletes the 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, nil - } - } - - return nil, fmt.Errorf("Failed to find registry for url: %s", URL) -} - -// GetRegistryByURL returns a registry that handles the types for a given URL. -func (rs *inmemRegistryService) GetRegistryByURL(URL string) (*common.Registry, 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) -} diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go deleted file mode 100644 index 27e94a5ff..000000000 --- a/pkg/registry/registry.go +++ /dev/null @@ -1,154 +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 ( - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" - - "fmt" - "net/url" - "regexp" - "strings" -) - -// Registry abstracts a registry that holds charts, which can be -// used in a Deployment Manager configuration. There can be multiple -// registry implementations. -type Registry interface { - // Also handles http.Client.Do method for authenticated File accesses - util.HTTPDoer - - // GetRegistryName returns the name of this registry - GetRegistryName() string - // GetRegistryType returns the type of this registry. - GetRegistryType() common.RegistryType - // GetRegistryShortURL returns the short URL for this registry. - GetRegistryShortURL() string - // GetRegistryFormat returns the format of this registry. - GetRegistryFormat() common.RegistryFormat - - // ListTypes lists types in this registry whose string values conform to the - // supplied regular expression, or all types, if the regular expression is nil. - ListTypes(regex *regexp.Regexp) ([]Type, error) - // GetDownloadURLs returns the URLs required to download the type contents. - GetDownloadURLs(t Type) ([]*url.URL, error) -} - -// GithubRegistry abstracts a registry that resides in a Github repository. -type GithubRegistry interface { - Registry // A GithubRegistry is a Registry. - // GetRegistryOwner returns the owner name for this registry - GetRegistryOwner() string - // GetRegistryRepository returns the repository name for this registry. - GetRegistryRepository() string - // GetRegistryPath returns the path to the registry in the repository. - GetRegistryPath() string -} - -// ObjectStorageRegistry abstracts a registry that resides in an Object Storage, for -// example Google Cloud Storage or AWS S3, etc. -type ObjectStorageRegistry interface { - Registry // An ObjectStorageRegistry is a Registry. - GetBucket() string -} - -// Type describes a type stored in a registry. -type Type struct { - Collection string - Name string - Version SemVer -} - -// NewType initializes a type -func NewType(collection, name, version string) (Type, error) { - result := Type{Collection: collection, Name: name} - err := result.SetVersion(version) - return result, err -} - -// NewTypeOrDie initializes a type and panics if initialization fails -func NewTypeOrDie(collection, name, version string) Type { - result, err := NewType(collection, name, version) - if err != nil { - panic(err) - } - - return result -} - -// Type conforms to the Stringer interface. -func (t Type) String() string { - var result string - if t.Collection != "" { - result = t.Collection + "/" - } - - result = result + t.Name - version := t.GetVersion() - if version != "" && version != "v0" { - result = result + ":" + version - } - - return result -} - -// GetVersion returns the type version with the letter "v" prepended. -func (t Type) GetVersion() string { - var result string - version := t.Version.String() - if version != "0" { - result = "v" + version - } - - return result -} - -// SetVersion strips the letter "v" from version, if present, -// and sets the the version of the type to the result. -func (t *Type) SetVersion(version string) error { - vstring := strings.TrimPrefix(version, "v") - s, err := ParseSemVer(vstring) - if err != nil { - return err - } - - t.Version = s - return nil -} - -// ParseType takes a registry type string and parses it into a *registry.Type. -// TODO: needs better validation that this is actually a registry type. -func ParseType(ts string) (Type, error) { - tt := Type{} - tList := strings.Split(ts, ":") - if len(tList) == 2 { - if err := tt.SetVersion(tList[1]); err != nil { - return tt, fmt.Errorf("malformed type string: %s", ts) - } - } - - cList := strings.Split(tList[0], "/") - if len(cList) == 1 { - tt.Name = tList[0] - } else { - tt.Collection = cList[0] - tt.Name = cList[1] - } - - return tt, nil -} diff --git a/pkg/registry/registry_test.go b/pkg/registry/registry_test.go deleted file mode 100644 index 3879fd37d..000000000 --- a/pkg/registry/registry_test.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2016 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 TestTypeConversion(t *testing.T) { - // TODO: Are there some real-world examples we want to validate here? - tests := map[string]Type{ - "foo": NewTypeOrDie("", "foo", ""), - "foo:v1": NewTypeOrDie("", "foo", "v1"), - "github.com/foo": NewTypeOrDie("github.com", "foo", ""), - "github.com/foo:v1.2.3": NewTypeOrDie("github.com", "foo", "v1.2.3"), - } - - for in, expect := range tests { - out, err := ParseType(in) - if err != nil { - t.Errorf("Error parsing type string %s: %s", in, err) - } - - if out.Name != expect.Name { - t.Errorf("Expected name to be %q, got %q", expect.Name, out.Name) - } - - if out.GetVersion() != expect.GetVersion() { - t.Errorf("Expected version to be %q, got %q", expect.GetVersion(), out.GetVersion()) - } - - if out.Collection != expect.Collection { - t.Errorf("Expected collection to be %q, got %q", expect.Collection, out.Collection) - } - - svalue := out.String() - if svalue != in { - t.Errorf("Expected string value to be %q, got %q", in, svalue) - } - } -} diff --git a/pkg/registry/registryprovider.go b/pkg/registry/registryprovider.go deleted file mode 100644 index 19c08d68e..000000000 --- a/pkg/registry/registryprovider.go +++ /dev/null @@ -1,421 +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 ( - "github.com/google/go-github/github" - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - storage "google.golang.org/api/storage/v1" - - "fmt" - "log" - "net/http" - "net/url" - "regexp" - "strings" - "sync" -) - -// RegistryProvider is a factory for Registry instances. -type RegistryProvider interface { - GetRegistryByShortURL(URL string) (Registry, error) - GetRegistryByName(registryName string) (Registry, error) -} - -type registryProvider struct { - sync.RWMutex - rs common.RegistryService - grp GithubRegistryProvider - gcsrp GCSRegistryProvider - cp common.CredentialProvider - registries map[string]Registry -} - -// NewDefaultRegistryProvider creates a default registry provider with the supplied credential. -func NewDefaultRegistryProvider(cp common.CredentialProvider, rs common.RegistryService) RegistryProvider { - return NewRegistryProvider(rs, NewGithubRegistryProvider(cp), NewGCSRegistryProvider(cp), cp) -} - -// NewRegistryProvider creates a new registry provider using the supplied arguments. -func NewRegistryProvider(rs common.RegistryService, grp GithubRegistryProvider, gcsrp GCSRegistryProvider, cp common.CredentialProvider) RegistryProvider { - if rs == nil { - rs = NewInmemRegistryService() - } - - if cp == nil { - cp = NewInmemCredentialProvider() - } - - if grp == nil { - grp = NewGithubRegistryProvider(cp) - } - - if gcsrp == nil { - gcsrp = NewGCSRegistryProvider(cp) - } - - registries := make(map[string]Registry) - rp := ®istryProvider{rs: rs, grp: grp, gcsrp: gcsrp, cp: cp, registries: registries} - return rp -} - -func (rp *registryProvider) getRegistry(cr common.Registry) (Registry, error) { - switch cr.Type { - case common.GithubRegistryType: - return rp.grp.GetGithubRegistry(cr) - case common.GCSRegistryType: - log.Printf("Creating a bigstore client using %#v", rp.gcsrp) - return rp.gcsrp.GetGCSRegistry(cr) - default: - return nil, fmt.Errorf("unknown registry type: %s", cr.Type) - } -} - -// GetRegistryByShortURL returns the registry identified by a short URL. -func (rp *registryProvider) GetRegistryByShortURL(URL string) (Registry, error) { - rp.RLock() - defer rp.RUnlock() - - result := rp.findRegistryByShortURL(URL) - if result == nil { - cr, err := rp.rs.GetByURL(URL) - if err != nil { - return nil, err - } - - r, err := rp.getRegistry(*cr) - if err != nil { - return nil, err - } - - rp.registries[r.GetRegistryName()] = r - result = r - } - - return result, nil -} - -// findRegistryByShortURL trims the scheme from both the supplied URL -// and the short URL returned by GetRegistryShortURL. -func (rp *registryProvider) findRegistryByShortURL(URL string) Registry { - trimmed := util.TrimURLScheme(URL) - for _, r := range rp.registries { - if strings.HasPrefix(trimmed, util.TrimURLScheme(r.GetRegistryShortURL())) { - return r - } - } - - return nil -} - -// GetRegistryByName returns a registry by name. -func (rp *registryProvider) GetRegistryByName(registryName string) (Registry, error) { - rp.RLock() - defer rp.RUnlock() - - cr, err := rp.rs.Get(registryName) - if err != nil { - return nil, err - } - - r, err := rp.getRegistry(*cr) - if err != nil { - return nil, err - } - - rp.registries[r.GetRegistryName()] = r - - return r, nil -} - -// ParseRegistryFormat creates a map from a registry format string. -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 -} - -// GithubRegistryProvider is a factory for GithubRegistry instances. -type GithubRegistryProvider interface { - GetGithubRegistry(cr common.Registry) (GithubRegistry, error) -} - -type githubRegistryProvider struct { - cp common.CredentialProvider -} - -// NewGithubRegistryProvider creates a GithubRegistryProvider. -func NewGithubRegistryProvider(cp common.CredentialProvider) GithubRegistryProvider { - if cp == nil { - // TODO: replace this panic with an error return. - panic(fmt.Errorf("no credential provider")) - } - return &githubRegistryProvider{cp: cp} -} - -func (grp githubRegistryProvider) createGithubClient(credentialName string) (*http.Client, *github.Client, error) { - if credentialName == "" { - return http.DefaultClient, github.NewClient(nil), nil - } - c, err := grp.cp.GetCredential(credentialName) - - if err != nil { - log.Printf("Failed to fetch credential %s: %v", credentialName, err) - log.Print("Trying to use unauthenticated client") - return http.DefaultClient, github.NewClient(nil), nil - } - - if c != nil { - if c.APIToken != "" { - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: string(c.APIToken)}, - ) - tc := oauth2.NewClient(oauth2.NoContext, ts) - return tc, github.NewClient(tc), nil - } - if c.BasicAuth.Username != "" && c.BasicAuth.Password != "" { - tp := github.BasicAuthTransport{ - Username: c.BasicAuth.Username, - Password: c.BasicAuth.Password, - } - return tp.Client(), github.NewClient(tp.Client()), nil - } - - } - return nil, nil, fmt.Errorf("No suitable credential found for %s", credentialName) - -} - -// GetGithubRegistry returns a new GithubRegistry. If there's a credential that is specified, will try -// to fetch it and use it, and if there's no credential found, will fall back to unauthenticated client. -func (grp githubRegistryProvider) GetGithubRegistry(cr common.Registry) (GithubRegistry, error) { - // If there's a credential that we need to use, fetch it and create a client for it. - httpClient, client, err := grp.createGithubClient(cr.CredentialName) - if err != nil { - return nil, err - } - - fMap := ParseRegistryFormat(cr.Format) - if fMap[common.UnversionedRegistry] && fMap[common.OneLevelRegistry] { - return NewGithubPackageRegistry(cr.Name, cr.URL, nil, httpClient, client) - } - - if fMap[common.VersionedRegistry] && fMap[common.CollectionRegistry] { - return NewGithubTemplateRegistry(cr.Name, cr.URL, nil, httpClient, client) - } - - return nil, fmt.Errorf("unknown registry format: %s", cr.Format) -} - -// GCSRegistryProvider is a factory for GCS Registry instances. -type GCSRegistryProvider interface { - GetGCSRegistry(cr common.Registry) (ObjectStorageRegistry, error) -} - -type gcsRegistryProvider struct { - cp common.CredentialProvider -} - -// NewGCSRegistryProvider creates a GCSRegistryProvider. -func NewGCSRegistryProvider(cp common.CredentialProvider) GCSRegistryProvider { - if cp == nil { - // TODO: replace this panic with an error return. - panic(fmt.Errorf("no credential provider")) - } - return &gcsRegistryProvider{cp: cp} -} - -// GetGCSRegistry returns a new Google Cloud Storage . If there's a credential that is specified, will try -// to fetch it and use it, and if there's no credential found, will fall back to unauthenticated client. -func (gcsrp gcsRegistryProvider) GetGCSRegistry(cr common.Registry) (ObjectStorageRegistry, error) { - client, err := gcsrp.createGCSClient(cr.CredentialName) - if err != nil { - return nil, err - } - service, err := storage.New(client) - if err != nil { - log.Fatalf("Unable to create storage service: %v", err) - } - return NewGCSRegistry(cr.Name, cr.URL, client, service) -} - -func (gcsrp gcsRegistryProvider) createGCSClient(credentialName string) (*http.Client, error) { - if credentialName == "" { - return http.DefaultClient, nil - } - - c, err := gcsrp.cp.GetCredential(credentialName) - if err != nil { - log.Printf("Failed to fetch credential %s: %v", credentialName, err) - log.Print("Trying to use unauthenticated client") - return http.DefaultClient, nil - } - - config, err := google.JWTConfigFromJSON([]byte(c.ServiceAccount), storage.DevstorageReadOnlyScope) - - if err != nil { - log.Fatalf("Unable to parse client secret file to config: %v", err) - } - return config.Client(oauth2.NoContext), nil -} - -// TemplateRegistryMatcher is an RE for a registry type that does support versions and has collections. -var TemplateRegistryMatcher = regexp.MustCompile("github.com/(.*)/(.*)/(.*)/(.*):(.*)") - -// PackageRegistryMatcher is an RE for a registry type that does not support versions and does not have collections. -var PackageRegistryMatcher = regexp.MustCompile("github.com/(.*)/(.*)/(.*)") - -// GCSRegistryMatcher is an RE for GCS storage -var GCSRegistryMatcher = regexp.MustCompile("gs://(.*)/(.*)") - -// 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) -} - -// IsGCSShortType returns whether a given type is a type description in a short format to GCS -func IsGCSShortType(t string) bool { - return strings.HasPrefix(t, "gs://") -} - -// 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, Registry, error) { - if IsGithubShortType(t) { - return ShortTypeToDownloadURLs(rp, t) - } else if IsGithubShortPackageType(t) { - return ShortTypeToPackageDownloadURLs(rp, t) - } else if IsGCSShortType(t) { - return ShortTypeToGCSDownloadUrls(rp, t) - } else if util.IsHTTPURL(t) { - result, err := url.Parse(t) - if err != nil { - return nil, nil, fmt.Errorf("cannot parse download URL %s: %s", t, err) - } - - return []string{result.String()}, nil, nil - } - - return []string{}, nil, 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, Registry, error) { - m := TemplateRegistryMatcher.FindStringSubmatch(t) - if len(m) != 6 { - return nil, nil, fmt.Errorf("cannot parse short github url: %s", t) - } - - r, err := rp.GetRegistryByShortURL(t) - if err != nil { - return nil, nil, err - } - - if r == nil { - return nil, nil, fmt.Errorf("cannot get github registry for %s", t) - } - - tt, err := NewType(m[3], m[4], m[5]) - if err != nil { - return nil, r, err - } - - urls, err := r.GetDownloadURLs(tt) - if err != nil { - return nil, r, err - } - - return util.ConvertURLsToStrings(urls), r, 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, Registry, error) { - m := PackageRegistryMatcher.FindStringSubmatch(t) - if len(m) != 4 { - return nil, nil, fmt.Errorf("Failed to parse short github url: %s", t) - } - - r, err := rp.GetRegistryByShortURL(t) - if err != nil { - return nil, nil, err - } - - tt, err := NewType("", m[3], "") - if err != nil { - return nil, r, err - } - - urls, err := r.GetDownloadURLs(tt) - if err != nil { - return nil, r, err - } - - return util.ConvertURLsToStrings(urls), r, err -} - -// ShortTypeToGCSDownloadUrls returns the download URLs for a short type name. -func ShortTypeToGCSDownloadUrls(rp RegistryProvider, t string) ([]string, Registry, error) { - m := GCSRegistryMatcher.FindStringSubmatch(t) - if len(m) != 3 { - return nil, nil, fmt.Errorf("Failed to parse short gs url: %s", t) - } - - r, err := rp.GetRegistryByShortURL(t) - if err != nil { - return nil, nil, err - } - tt, err := NewType(m[1], m[2], "") - if err != nil { - return nil, r, err - } - - urls, err := r.GetDownloadURLs(tt) - if err != nil { - return nil, r, err - } - return util.ConvertURLsToStrings(urls), r, err -} diff --git a/pkg/registry/registryprovider_test.go b/pkg/registry/registryprovider_test.go deleted file mode 100644 index 968d51a8a..000000000 --- a/pkg/registry/registryprovider_test.go +++ /dev/null @@ -1,67 +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 ( - "testing" -) - -func testURLConversionDriver(rp RegistryProvider, tests map[string]TestURLAndError, t *testing.T) { - for in, expected := range tests { - // TODO(vaikas): Test to make sure it's the right registry. - 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"): {"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", nil}, - NewTypeOrDie("storage", "redis", "v1"): {"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": {"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", nil}, - "github.com/kubernetes/application-dm-templates/storage/redis:v1": {"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/storage/redis/v1/redis.jinja", nil}, - } - - grp := NewTestGithubRegistryProvider("github.com/kubernetes/application-dm-templates", githubURLMaps) - // TODO(vaikas): XXXX FIXME Add gcsrp - testURLConversionDriver(NewRegistryProvider(nil, grp, nil, NewInmemCredentialProvider()), tests, t) -} - -func TestShortGithubURLPackageMapping(t *testing.T) { - githubURLMaps := map[Type]TestURLAndError{ - NewTypeOrDie("", "mongodb", ""): {"https://raw.githubusercontent.com/helm/charts/master/mongodb/manifests/mongodb.yaml", nil}, - NewTypeOrDie("", "redis", ""): {"https://raw.githubusercontent.com/helm/charts/master/redis/manifests/redis.yaml", nil}, - } - - tests := map[string]TestURLAndError{ - "github.com/helm/charts/mongodb": {"https://raw.githubusercontent.com/helm/charts/master/mongodb/manifests/mongodb.yaml", nil}, - "github.com/helm/charts/redis": {"https://raw.githubusercontent.com/helm/charts/master/redis/manifests/redis.yaml", nil}, - } - - grp := NewTestGithubRegistryProvider("github.com/helm/charts", githubURLMaps) - // TODO(vaikas): XXXX FIXME Add gcsrp - testURLConversionDriver(NewRegistryProvider(nil, grp, nil, NewInmemCredentialProvider()), tests, t) -} diff --git a/pkg/registry/secrets_credential_provider.go b/pkg/registry/secrets_credential_provider.go deleted file mode 100644 index 2adaaf725..000000000 --- a/pkg/registry/secrets_credential_provider.go +++ /dev/null @@ -1,128 +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 ( - "encoding/base64" - "encoding/json" - "flag" - "fmt" - "log" - - "github.com/ghodss/yaml" - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" -) - -var ( - kubePath = flag.String("kubectl", "./kubectl", "The path to the kubectl binary.") - kubeService = flag.String("service", "", "The DNS name of the kubernetes service.") - kubeServer = flag.String("server", "", "The IP address and optional port of the kubernetes master.") - kubeInsecure = flag.Bool("insecure-skip-tls-verify", false, "Do not check the server's certificate for validity.") - kubeConfig = flag.String("config", "", "Path to a kubeconfig file.") - kubeCertAuth = flag.String("certificate-authority", "", "Path to a file for the certificate authority.") - kubeClientCert = flag.String("client-certificate", "", "Path to a client certificate file.") - kubeClientKey = flag.String("client-key", "", "Path to a client key file.") - kubeToken = flag.String("token", "", "A service account token.") - kubeUsername = flag.String("username", "", "The username to use for basic auth.") - kubePassword = flag.String("password", "", "The password to use for basic auth.") -) - -var kubernetesConfig *util.KubernetesConfig - -const secretType = "Secret" - -// SecretsCredentialProvider provides credentials for registries from Kubernertes secrets. -type SecretsCredentialProvider struct { - // Actual object that talks to secrets service. - k util.Kubernetes -} - -// NewSecretsCredentialProvider creates a new secrets credential provider. -func NewSecretsCredentialProvider() common.CredentialProvider { - kubernetesConfig := &util.KubernetesConfig{ - KubePath: *kubePath, - KubeService: *kubeService, - KubeServer: *kubeServer, - KubeInsecure: *kubeInsecure, - KubeConfig: *kubeConfig, - KubeCertAuth: *kubeCertAuth, - KubeClientCert: *kubeClientCert, - KubeClientKey: *kubeClientKey, - KubeToken: *kubeToken, - KubeUsername: *kubeUsername, - KubePassword: *kubePassword, - } - return &SecretsCredentialProvider{util.NewKubernetesKubectl(kubernetesConfig)} -} - -func parseCredential(credential string) (*common.RegistryCredential, error) { - var c util.KubernetesSecret - if err := json.Unmarshal([]byte(credential), &c); err != nil { - return nil, fmt.Errorf("cannot unmarshal credential '%s' (%#v)", credential, err) - } - - d, err := base64.StdEncoding.DecodeString(c.Data["credential"]) - if err != nil { - return nil, fmt.Errorf("cannot unmarshal credential '%s' (%#v)", c, err) - } - // And then finally unmarshal it from yaml to common.RegistryCredential - r := &common.RegistryCredential{} - if err := yaml.Unmarshal(d, &r); err != nil { - return nil, fmt.Errorf("cannot unmarshal credential %s (%#v)", c, err) - } - return r, nil -} - -// GetCredential returns a credential by name. -func (scp *SecretsCredentialProvider) GetCredential(name string) (*common.RegistryCredential, error) { - o, err := scp.k.Get(name, secretType) - if err != nil { - return nil, err - } - return parseCredential(o) -} - -// SetCredential sets a credential by name. -func (scp *SecretsCredentialProvider) SetCredential(name string, credential *common.RegistryCredential) error { - // Marshal the credential & base64 encode it. - b, err := yaml.Marshal(credential) - if err != nil { - log.Printf("yaml marshal failed for credential: %s: %v", name, err) - return err - } - enc := base64.StdEncoding.EncodeToString(b) - - // Then create a kubernetes object out of it - metadata := make(map[string]string) - metadata["name"] = name - data := make(map[string]string) - data["credential"] = enc - obj := &util.KubernetesSecret{ - Kind: secretType, - APIVersion: "v1", - Metadata: metadata, - Data: data, - } - ko, err := yaml.Marshal(obj) - if err != nil { - log.Printf("yaml marshal failed for kubernetes object: %s: %v", name, err) - return err - } - _, err = scp.k.Create(string(ko)) - return err -} diff --git a/pkg/registry/semver.go b/pkg/registry/semver.go deleted file mode 100644 index 0a42e2d33..000000000 --- a/pkg/registry/semver.go +++ /dev/null @@ -1,92 +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" - "strconv" - "strings" -) - -// SemVer holds a semantic version as defined by semver.io. -type SemVer struct { - Major uint - Minor uint - Patch uint -} - -// ParseSemVer parses a semantic version string. -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 -} - -// IsZero returns true if the semantic version is zero. -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 -} diff --git a/pkg/registry/semver_test.go b/pkg/registry/semver_test.go deleted file mode 100644 index b88c7455c..000000000 --- a/pkg/registry/semver_test.go +++ /dev/null @@ -1,91 +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 ( - "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) - } - } -} diff --git a/pkg/registry/test/test_credentials_file.yaml b/pkg/registry/test/test_credentials_file.yaml deleted file mode 100644 index 8ada52807..000000000 --- a/pkg/registry/test/test_credentials_file.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- name: test1 - apitoken: token -- name: test2 - basicauth: - username: user - password: password diff --git a/pkg/registry/testhelper.go b/pkg/registry/testhelper.go deleted file mode 100644 index 30e76e386..000000000 --- a/pkg/registry/testhelper.go +++ /dev/null @@ -1,152 +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 - -// TODO(jackgr): Mock github repository service to test package and template registry implementations. - -import ( - "bytes" - "io/ioutil" - - "github.com/kubernetes/helm/pkg/common" - "github.com/kubernetes/helm/pkg/util" - - "fmt" - "net/http" - "net/url" - "regexp" - "strings" -) - -// TestURLAndError associates a URL with an error string for testing. -type TestURLAndError struct { - URL string - Err error -} - -// DownloadResponse holds a mock http response for testing. -type DownloadResponse struct { - Err error - Code int - Body string -} - -type testGithubRegistryProvider struct { - shortURL string - responses map[Type]TestURLAndError - downloadResponses map[string]DownloadResponse -} - -type testGithubRegistry struct { - githubRegistry - responses map[Type]TestURLAndError - downloadResponses map[string]DownloadResponse -} - -// NewTestGithubRegistryProvider creates a test github registry provider. -func NewTestGithubRegistryProvider(shortURL string, responses map[Type]TestURLAndError) GithubRegistryProvider { - return testGithubRegistryProvider{ - shortURL: util.TrimURLScheme(shortURL), - responses: responses, - } -} - -// NewTestGithubRegistryProviderWithDownloads creates a test github registry provider with download responses. -func NewTestGithubRegistryProviderWithDownloads(shortURL string, responses map[Type]TestURLAndError, downloadResponses map[string]DownloadResponse) GithubRegistryProvider { - return testGithubRegistryProvider{ - shortURL: util.TrimURLScheme(shortURL), - responses: responses, - downloadResponses: downloadResponses, - } -} - -// GetGithubRegistry is a mock implementation of the same method on GithubRegistryProvider. -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, http.DefaultClient, nil) - if err != nil { - panic(fmt.Errorf("cannot create a github registry: %s", err)) - } - - return &testGithubRegistry{ - githubRegistry: *ghr, - responses: tgrp.responses, - downloadResponses: tgrp.downloadResponses, - }, nil - } - - panic(fmt.Errorf("unknown registry: %v", cr)) -} - -// ListTypes is a mock implementation of the same method on GithubRegistryProvider. -func (tgr testGithubRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) { - panic(fmt.Errorf("ListTypes should not be called in the test")) -} - -// GetDownloadURLs is a mock implementation of the same method on GithubRegistryProvider. -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 -} - -// Do is a mock implementation of the same method on GithubRegistryProvider. -func (tgr testGithubRegistry) Do(req *http.Request) (resp *http.Response, err error) { - response := tgr.downloadResponses[req.URL.String()] - return &http.Response{StatusCode: response.Code, Body: ioutil.NopCloser(bytes.NewBufferString(response.Body))}, response.Err -} - -type testGCSRegistryProvider struct { - shortURL string - responses map[Type]TestURLAndError -} - -type testGCSRegistry struct { - GCSRegistry - responses map[Type]TestURLAndError -} - -// NewTestGCSRegistryProvider creates a test GCS registry provider. -func NewTestGCSRegistryProvider(shortURL string, responses map[Type]TestURLAndError) GCSRegistryProvider { - return testGCSRegistryProvider{ - shortURL: util.TrimURLScheme(shortURL), - responses: responses, - } -} - -// GetDownloadURLs is a mock implementation of the same method on GCSRegistryProvider. -func (tgrp testGCSRegistryProvider) GetGCSRegistry(cr common.Registry) (ObjectStorageRegistry, error) { - trimmed := util.TrimURLScheme(cr.URL) - if strings.HasPrefix(trimmed, tgrp.shortURL) { - gcsr, err := NewGCSRegistry(cr.Name, trimmed, http.DefaultClient, nil) - if err != nil { - panic(fmt.Errorf("cannot create gcs registry: %s", err)) - } - - return &testGCSRegistry{ - GCSRegistry: *gcsr, - responses: tgrp.responses, - }, nil - } - - panic(fmt.Errorf("unknown registry: %v", cr)) -}