Commit 9074ab56 authored by Jack Greenfield's avatar Jack Greenfield

Merge pull request #433 from jackgr/public-repo

Make Repo struct public and fix style errors
parents 2724b903 511ac5d1
...@@ -27,17 +27,17 @@ import ( ...@@ -27,17 +27,17 @@ import (
// FilebasedCredentialProvider provides credentials for registries. // FilebasedCredentialProvider provides credentials for registries.
type FilebasedCredentialProvider struct { type FilebasedCredentialProvider struct {
// Actual backing store // Actual backing store
backingCredentialProvider CredentialProvider backingCredentialProvider ICredentialProvider
} }
// NamedRepoCredential associates a name with a RepoCredential. // NamedRepoCredential associates a name with a Credential.
type NamedRepoCredential struct { type NamedRepoCredential struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
RepoCredential Credential
} }
// NewFilebasedCredentialProvider creates a file based credential provider. // NewFilebasedCredentialProvider creates a file based credential provider.
func NewFilebasedCredentialProvider(filename string) (CredentialProvider, error) { func NewFilebasedCredentialProvider(filename string) (ICredentialProvider, error) {
icp := NewInmemCredentialProvider() icp := NewInmemCredentialProvider()
log.Printf("Using credentials file %s", filename) log.Printf("Using credentials file %s", filename)
c, err := readCredentialsFile(filename) c, err := readCredentialsFile(filename)
...@@ -47,7 +47,7 @@ func NewFilebasedCredentialProvider(filename string) (CredentialProvider, error) ...@@ -47,7 +47,7 @@ func NewFilebasedCredentialProvider(filename string) (CredentialProvider, error)
for _, nc := range c { for _, nc := range c {
log.Printf("Loading credential named %s", nc.Name) log.Printf("Loading credential named %s", nc.Name)
icp.SetCredential(nc.Name, &nc.RepoCredential) icp.SetCredential(nc.Name, &nc.Credential)
} }
return &FilebasedCredentialProvider{icp}, nil return &FilebasedCredentialProvider{icp}, nil
...@@ -72,11 +72,11 @@ func parseCredentials(bytes []byte) ([]NamedRepoCredential, error) { ...@@ -72,11 +72,11 @@ func parseCredentials(bytes []byte) ([]NamedRepoCredential, error) {
} }
// GetCredential returns a credential by name. // GetCredential returns a credential by name.
func (fcp *FilebasedCredentialProvider) GetCredential(name string) (*RepoCredential, error) { func (fcp *FilebasedCredentialProvider) GetCredential(name string) (*Credential, error) {
return fcp.backingCredentialProvider.GetCredential(name) return fcp.backingCredentialProvider.GetCredential(name)
} }
// SetCredential sets a credential by name. // SetCredential sets a credential by name.
func (fcp *FilebasedCredentialProvider) SetCredential(name string, credential *RepoCredential) error { func (fcp *FilebasedCredentialProvider) SetCredential(name string, credential *Credential) error {
return fmt.Errorf("SetCredential operation not supported with FilebasedCredentialProvider") return fmt.Errorf("SetCredential operation not supported with FilebasedCredentialProvider")
} }
...@@ -24,7 +24,7 @@ var filename = "./testdata/test_credentials_file.yaml" ...@@ -24,7 +24,7 @@ var filename = "./testdata/test_credentials_file.yaml"
type filebasedTestCase struct { type filebasedTestCase struct {
name string name string
exp *RepoCredential exp *Credential
expErr error expErr error
} }
...@@ -36,18 +36,18 @@ func TestNotExistFilebased(t *testing.T) { ...@@ -36,18 +36,18 @@ func TestNotExistFilebased(t *testing.T) {
func TestGetApiTokenFilebased(t *testing.T) { func TestGetApiTokenFilebased(t *testing.T) {
cp := getProvider(t) cp := getProvider(t)
tc := &testCase{"test1", &RepoCredential{APIToken: "token"}, nil} tc := &testCase{"test1", &Credential{APIToken: "token"}, nil}
testGetCredential(t, cp, tc) testGetCredential(t, cp, tc)
} }
func TestSetAndGetBasicAuthFilebased(t *testing.T) { func TestSetAndGetBasicAuthFilebased(t *testing.T) {
cp := getProvider(t) cp := getProvider(t)
ba := BasicAuthCredential{Username: "user", Password: "password"} ba := BasicAuthCredential{Username: "user", Password: "password"}
tc := &testCase{"test2", &RepoCredential{BasicAuth: ba}, nil} tc := &testCase{"test2", &Credential{BasicAuth: ba}, nil}
testGetCredential(t, cp, tc) testGetCredential(t, cp, tc)
} }
func getProvider(t *testing.T) CredentialProvider { func getProvider(t *testing.T) ICredentialProvider {
cp, err := NewFilebasedCredentialProvider(filename) cp, err := NewFilebasedCredentialProvider(filename)
if err != nil { if err != nil {
t.Fatalf("cannot create a new provider from file %s: %s", filename, err) t.Fatalf("cannot create a new provider from file %s: %s", filename, err)
......
...@@ -37,7 +37,7 @@ var GCSChartURLMatcher = regexp.MustCompile("gs://(.*)/(.*)-(.*).tgz") ...@@ -37,7 +37,7 @@ var GCSChartURLMatcher = regexp.MustCompile("gs://(.*)/(.*)-(.*).tgz")
const ( const (
// GCSRepoType identifies the GCS repository type. // GCSRepoType identifies the GCS repository type.
GCSRepoType = RepoType("gcs") GCSRepoType = ERepoType("gcs")
// GCSRepoFormat identifies the GCS repository format. // GCSRepoFormat identifies the GCS repository format.
// In a GCS repository all charts appear at the top level. // In a GCS repository all charts appear at the top level.
...@@ -53,21 +53,21 @@ const ( ...@@ -53,21 +53,21 @@ const (
GCSPublicRepoBucket = GCSPublicRepoName GCSPublicRepoBucket = GCSPublicRepoName
) )
// gcsRepo implements the ObjectStorageRepo interface for Google Cloud Storage. // GCSRepo implements the IStorageRepo interface for Google Cloud Storage.
type gcsRepo struct { type GCSRepo struct {
repo Repo
bucket string bucket string
httpClient *http.Client httpClient *http.Client
service *storage.Service service *storage.Service
} }
// NewPublicGCSRepo creates a new an ObjectStorageRepo for the public GCS repository. // NewPublicGCSRepo creates a new an IStorageRepo for the public GCS repository.
func NewPublicGCSRepo(httpClient *http.Client) (ObjectStorageRepo, error) { func NewPublicGCSRepo(httpClient *http.Client) (IStorageRepo, error) {
return NewGCSRepo(GCSPublicRepoName, GCSPublicRepoURL, "", nil) return NewGCSRepo(GCSPublicRepoName, GCSPublicRepoURL, "", nil)
} }
// NewGCSRepo creates a new ObjectStorageRepo for a given GCS repository. // NewGCSRepo creates a new IStorageRepo for a given GCS repository.
func NewGCSRepo(name, URL, credentialName string, httpClient *http.Client) (ObjectStorageRepo, error) { func NewGCSRepo(name, URL, credentialName string, httpClient *http.Client) (IStorageRepo, error) {
r, err := newRepo(name, URL, credentialName, GCSRepoFormat, GCSRepoType) r, err := newRepo(name, URL, credentialName, GCSRepoFormat, GCSRepoType)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -76,7 +76,7 @@ func NewGCSRepo(name, URL, credentialName string, httpClient *http.Client) (Obje ...@@ -76,7 +76,7 @@ func NewGCSRepo(name, URL, credentialName string, httpClient *http.Client) (Obje
return newGCSRepo(r, httpClient) return newGCSRepo(r, httpClient)
} }
func newGCSRepo(r *repo, httpClient *http.Client) (*gcsRepo, error) { func newGCSRepo(r *Repo, httpClient *http.Client) (*GCSRepo, error) {
URL := r.GetURL() URL := r.GetURL()
m := GCSRepoURLMatcher.FindStringSubmatch(URL) m := GCSRepoURLMatcher.FindStringSubmatch(URL)
if len(m) != 2 { if len(m) != 2 {
...@@ -96,8 +96,8 @@ func newGCSRepo(r *repo, httpClient *http.Client) (*gcsRepo, error) { ...@@ -96,8 +96,8 @@ func newGCSRepo(r *repo, httpClient *http.Client) (*gcsRepo, error) {
return nil, fmt.Errorf("cannot create storage service for %s: %s", URL, err) return nil, fmt.Errorf("cannot create storage service for %s: %s", URL, err)
} }
gcsr := &gcsRepo{ gcsr := &GCSRepo{
repo: *r, Repo: *r,
httpClient: httpClient, httpClient: httpClient,
service: gcs, service: gcs,
bucket: m[1], bucket: m[1],
...@@ -106,7 +106,7 @@ func newGCSRepo(r *repo, httpClient *http.Client) (*gcsRepo, error) { ...@@ -106,7 +106,7 @@ func newGCSRepo(r *repo, httpClient *http.Client) (*gcsRepo, error) {
return gcsr, nil return gcsr, nil
} }
func validateRepoType(repoType RepoType) error { func validateRepoType(repoType ERepoType) error {
switch repoType { switch repoType {
case GCSRepoType: case GCSRepoType:
return nil return nil
...@@ -117,7 +117,7 @@ func validateRepoType(repoType RepoType) error { ...@@ -117,7 +117,7 @@ func validateRepoType(repoType RepoType) error {
// ListCharts lists charts in this chart repository whose string values conform to the // ListCharts lists charts in this chart repository whose string values conform to the
// supplied regular expression, or all charts, if the regular expression is nil. // supplied regular expression, or all charts, if the regular expression is nil.
func (g *gcsRepo) ListCharts(regex *regexp.Regexp) ([]string, error) { func (g *GCSRepo) ListCharts(regex *regexp.Regexp) ([]string, error) {
charts := []string{} charts := []string{}
// List all objects in a bucket using pagination // List all objects in a bucket using pagination
...@@ -155,7 +155,7 @@ func (g *gcsRepo) ListCharts(regex *regexp.Regexp) ([]string, error) { ...@@ -155,7 +155,7 @@ func (g *gcsRepo) ListCharts(regex *regexp.Regexp) ([]string, error) {
} }
// GetChart retrieves, unpacks and returns a chart by name. // GetChart retrieves, unpacks and returns a chart by name.
func (g *gcsRepo) GetChart(name string) (*chart.Chart, error) { func (g *GCSRepo) GetChart(name string) (*chart.Chart, error) {
// Charts should be named bucket/chart-X.Y.Z.tgz, so check that the name matches // Charts should be named bucket/chart-X.Y.Z.tgz, so check that the name matches
if !ChartNameMatcher.MatchString(name) { if !ChartNameMatcher.MatchString(name) {
return nil, fmt.Errorf("name must be of the form <name>-<version>.tgz, was %s", name) return nil, fmt.Errorf("name must be of the form <name>-<version>.tgz, was %s", name)
...@@ -184,11 +184,11 @@ func (g *gcsRepo) GetChart(name string) (*chart.Chart, error) { ...@@ -184,11 +184,11 @@ func (g *gcsRepo) GetChart(name string) (*chart.Chart, error) {
} }
// GetBucket returns the repository bucket. // GetBucket returns the repository bucket.
func (g *gcsRepo) GetBucket() string { func (g *GCSRepo) GetBucket() string {
return g.bucket return g.bucket
} }
// Do performs an HTTP operation on the receiver's httpClient. // Do performs an HTTP operation on the receiver's httpClient.
func (g *gcsRepo) Do(req *http.Request) (resp *http.Response, err error) { func (g *GCSRepo) Do(req *http.Request) (resp *http.Response, err error) {
return g.httpClient.Do(req) return g.httpClient.Do(req)
} }
...@@ -125,7 +125,7 @@ func TestGetChartWithInvalidName(t *testing.T) { ...@@ -125,7 +125,7 @@ func TestGetChartWithInvalidName(t *testing.T) {
} }
} }
func getTestRepo(t *testing.T) ObjectStorageRepo { func getTestRepo(t *testing.T) IStorageRepo {
tr, err := NewGCSRepo(TestRepoName, TestRepoURL, TestRepoCredentialName, nil) tr, err := NewGCSRepo(TestRepoName, TestRepoURL, TestRepoCredentialName, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
...@@ -24,16 +24,16 @@ import ( ...@@ -24,16 +24,16 @@ import (
// InmemCredentialProvider is a memory based credential provider. // InmemCredentialProvider is a memory based credential provider.
type InmemCredentialProvider struct { type InmemCredentialProvider struct {
sync.RWMutex sync.RWMutex
credentials map[string]*RepoCredential credentials map[string]*Credential
} }
// NewInmemCredentialProvider creates a new memory based credential provider. // NewInmemCredentialProvider creates a new memory based credential provider.
func NewInmemCredentialProvider() CredentialProvider { func NewInmemCredentialProvider() ICredentialProvider {
return &InmemCredentialProvider{credentials: make(map[string]*RepoCredential)} return &InmemCredentialProvider{credentials: make(map[string]*Credential)}
} }
// GetCredential returns a credential by name. // GetCredential returns a credential by name.
func (fcp *InmemCredentialProvider) GetCredential(name string) (*RepoCredential, error) { func (fcp *InmemCredentialProvider) GetCredential(name string) (*Credential, error) {
fcp.RLock() fcp.RLock()
defer fcp.RUnlock() defer fcp.RUnlock()
...@@ -45,10 +45,10 @@ func (fcp *InmemCredentialProvider) GetCredential(name string) (*RepoCredential, ...@@ -45,10 +45,10 @@ func (fcp *InmemCredentialProvider) GetCredential(name string) (*RepoCredential,
} }
// SetCredential sets a credential by name. // SetCredential sets a credential by name.
func (fcp *InmemCredentialProvider) SetCredential(name string, credential *RepoCredential) error { func (fcp *InmemCredentialProvider) SetCredential(name string, credential *Credential) error {
fcp.Lock() fcp.Lock()
defer fcp.Unlock() defer fcp.Unlock()
fcp.credentials[name] = &RepoCredential{APIToken: credential.APIToken, BasicAuth: credential.BasicAuth, ServiceAccount: credential.ServiceAccount} fcp.credentials[name] = &Credential{APIToken: credential.APIToken, BasicAuth: credential.BasicAuth, ServiceAccount: credential.ServiceAccount}
return nil return nil
} }
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
type testCase struct { type testCase struct {
name string name string
exp *RepoCredential exp *Credential
expErr error expErr error
} }
...@@ -32,7 +32,7 @@ func createMissingError(name string) error { ...@@ -32,7 +32,7 @@ func createMissingError(name string) error {
return fmt.Errorf("no such credential: %s", name) return fmt.Errorf("no such credential: %s", name)
} }
func testGetCredential(t *testing.T, cp CredentialProvider, tc *testCase) { func testGetCredential(t *testing.T, cp ICredentialProvider, tc *testCase) {
actual, actualErr := cp.GetCredential(tc.name) actual, actualErr := cp.GetCredential(tc.name)
if !reflect.DeepEqual(actual, tc.exp) { if !reflect.DeepEqual(actual, tc.exp) {
t.Fatalf("test case %s failed: want: %#v, have: %#v", tc.name, tc.exp, actual) t.Fatalf("test case %s failed: want: %#v, have: %#v", tc.name, tc.exp, actual)
...@@ -43,7 +43,7 @@ func testGetCredential(t *testing.T, cp CredentialProvider, tc *testCase) { ...@@ -43,7 +43,7 @@ func testGetCredential(t *testing.T, cp CredentialProvider, tc *testCase) {
} }
} }
func verifySetAndGetCredential(t *testing.T, cp CredentialProvider, tc *testCase) { func verifySetAndGetCredential(t *testing.T, cp ICredentialProvider, tc *testCase) {
err := cp.SetCredential(tc.name, tc.exp) err := cp.SetCredential(tc.name, tc.exp)
if err != nil { if err != nil {
t.Fatalf("test case %s failed: cannot set credential: %v", tc.name, err) t.Fatalf("test case %s failed: cannot set credential: %v", tc.name, err)
...@@ -60,13 +60,13 @@ func TestNotExist(t *testing.T) { ...@@ -60,13 +60,13 @@ func TestNotExist(t *testing.T) {
func TestSetAndGetApiToken(t *testing.T) { func TestSetAndGetApiToken(t *testing.T) {
cp := NewInmemCredentialProvider() cp := NewInmemCredentialProvider()
tc := &testCase{"testcredential", &RepoCredential{APIToken: "some token here"}, nil} tc := &testCase{"testcredential", &Credential{APIToken: "some token here"}, nil}
verifySetAndGetCredential(t, cp, tc) verifySetAndGetCredential(t, cp, tc)
} }
func TestSetAndGetBasicAuth(t *testing.T) { func TestSetAndGetBasicAuth(t *testing.T) {
cp := NewInmemCredentialProvider() cp := NewInmemCredentialProvider()
ba := BasicAuthCredential{Username: "user", Password: "pass"} ba := BasicAuthCredential{Username: "user", Password: "pass"}
tc := &testCase{"testcredential", &RepoCredential{BasicAuth: ba}, nil} tc := &testCase{"testcredential", &Credential{BasicAuth: ba}, nil}
verifySetAndGetCredential(t, cp, tc) verifySetAndGetCredential(t, cp, tc)
} }
...@@ -24,13 +24,13 @@ import ( ...@@ -24,13 +24,13 @@ import (
type inmemRepoService struct { type inmemRepoService struct {
sync.RWMutex sync.RWMutex
repositories map[string]Repo repositories map[string]IRepo
} }
// NewInmemRepoService returns a new memory based repository service. // NewInmemRepoService returns a new memory based repository service.
func NewInmemRepoService() Service { func NewInmemRepoService() IRepoService {
rs := &inmemRepoService{ rs := &inmemRepoService{
repositories: make(map[string]Repo), repositories: make(map[string]IRepo),
} }
r, err := NewPublicGCSRepo(nil) r, err := NewPublicGCSRepo(nil)
...@@ -42,11 +42,11 @@ func NewInmemRepoService() Service { ...@@ -42,11 +42,11 @@ func NewInmemRepoService() Service {
} }
// List returns the list of all known chart repositories // List returns the list of all known chart repositories
func (rs *inmemRepoService) List() ([]Repo, error) { func (rs *inmemRepoService) List() ([]IRepo, error) {
rs.RLock() rs.RLock()
defer rs.RUnlock() defer rs.RUnlock()
ret := []Repo{} ret := []IRepo{}
for _, r := range rs.repositories { for _, r := range rs.repositories {
ret = append(ret, r) ret = append(ret, r)
} }
...@@ -55,7 +55,7 @@ func (rs *inmemRepoService) List() ([]Repo, error) { ...@@ -55,7 +55,7 @@ func (rs *inmemRepoService) List() ([]Repo, error) {
} }
// Create adds a known repository to the list // Create adds a known repository to the list
func (rs *inmemRepoService) Create(repository Repo) error { func (rs *inmemRepoService) Create(repository IRepo) error {
rs.Lock() rs.Lock()
defer rs.Unlock() defer rs.Unlock()
...@@ -70,7 +70,7 @@ func (rs *inmemRepoService) Create(repository Repo) error { ...@@ -70,7 +70,7 @@ func (rs *inmemRepoService) Create(repository Repo) error {
} }
// Get returns the repository with the given name // Get returns the repository with the given name
func (rs *inmemRepoService) Get(name string) (Repo, error) { func (rs *inmemRepoService) Get(name string) (IRepo, error) {
rs.RLock() rs.RLock()
defer rs.RUnlock() defer rs.RUnlock()
...@@ -83,11 +83,11 @@ func (rs *inmemRepoService) Get(name string) (Repo, error) { ...@@ -83,11 +83,11 @@ func (rs *inmemRepoService) Get(name string) (Repo, error) {
} }
// GetByURL returns the repository that backs the given URL // GetByURL returns the repository that backs the given URL
func (rs *inmemRepoService) GetByURL(URL string) (Repo, error) { func (rs *inmemRepoService) GetByURL(URL string) (IRepo, error) {
rs.RLock() rs.RLock()
defer rs.RUnlock() defer rs.RUnlock()
var found Repo var found IRepo
for _, r := range rs.repositories { for _, r := range rs.repositories {
rURL := r.GetURL() rURL := r.GetURL()
if strings.HasPrefix(URL, rURL) { if strings.HasPrefix(URL, rURL) {
......
...@@ -21,21 +21,12 @@ import ( ...@@ -21,21 +21,12 @@ import (
"net/url" "net/url"
) )
// repo describes a repository // NewRepo takes params and returns a IRepo
type repo struct { func NewRepo(name, URL, credentialName, repoFormat, repoType string) (IRepo, error) {
Name string `json:"name"` // Friendly name for this repository return newRepo(name, URL, credentialName, ERepoFormat(repoFormat), ERepoType(repoType))
URL string `json:"url"` // URL to the root of this repository
CredentialName string `json:"credentialname"` // Credential name used to access this repository
Format RepoFormat `json:"format"` // Format of this repository
Type RepoType `json:"type"` // Technology implementing this repository
} }
// NewRepo takes params and returns a Repo func newRepo(name, URL, credentialName string, repoFormat ERepoFormat, repoType ERepoType) (*Repo, error) {
func NewRepo(name, URL, credentialName, repoFormat, repoType string) (Repo, error) {
return newRepo(name, URL, credentialName, RepoFormat(repoFormat), RepoType(repoType))
}
func newRepo(name, URL, credentialName string, repoFormat RepoFormat, repoType RepoType) (*repo, error) {
if name == "" { if name == "" {
return nil, fmt.Errorf("name must not be empty") return nil, fmt.Errorf("name must not be empty")
} }
...@@ -53,7 +44,7 @@ func newRepo(name, URL, credentialName string, repoFormat RepoFormat, repoType R ...@@ -53,7 +44,7 @@ func newRepo(name, URL, credentialName string, repoFormat RepoFormat, repoType R
return nil, err return nil, err
} }
r := &repo{ r := &Repo{
Name: name, Name: name,
Type: repoType, Type: repoType,
URL: URL, URL: URL,
...@@ -65,7 +56,7 @@ func newRepo(name, URL, credentialName string, repoFormat RepoFormat, repoType R ...@@ -65,7 +56,7 @@ func newRepo(name, URL, credentialName string, repoFormat RepoFormat, repoType R
} }
// Currently, only flat repositories are supported. // Currently, only flat repositories are supported.
func validateRepoFormat(repoFormat RepoFormat) error { func validateRepoFormat(repoFormat ERepoFormat) error {
switch repoFormat { switch repoFormat {
case FlatRepoFormat: case FlatRepoFormat:
return nil return nil
...@@ -75,39 +66,39 @@ func validateRepoFormat(repoFormat RepoFormat) error { ...@@ -75,39 +66,39 @@ func validateRepoFormat(repoFormat RepoFormat) error {
} }
// GetName returns the friendly name of this repository. // GetName returns the friendly name of this repository.
func (r *repo) GetName() string { func (r *Repo) GetName() string {
return r.Name return r.Name
} }
// GetType returns the technology implementing this repository. // GetType returns the technology implementing this repository.
func (r *repo) GetType() RepoType { func (r *Repo) GetType() ERepoType {
return r.Type return r.Type
} }
// GetURL returns the URL to the root of this repository. // GetURL returns the URL to the root of this repository.
func (r *repo) GetURL() string { func (r *Repo) GetURL() string {
return r.URL return r.URL
} }
// GetFormat returns the format of this repository. // GetFormat returns the format of this repository.
func (r *repo) GetFormat() RepoFormat { func (r *Repo) GetFormat() ERepoFormat {
return r.Format return r.Format
} }
// GetCredentialName returns the credential name used to access this repository. // GetCredentialName returns the credential name used to access this repository.
func (r *repo) GetCredentialName() string { func (r *Repo) GetCredentialName() string {
return r.CredentialName return r.CredentialName
} }
func validateRepo(tr Repo, wantName, wantURL, wantCredentialName string, wantFormat RepoFormat, wantType RepoType) error { func validateRepo(tr IRepo, wantName, wantURL, wantCredentialName string, wantFormat ERepoFormat, wantType ERepoType) error {
haveName := tr.GetName() haveName := tr.GetName()
if haveName != wantName { if haveName != wantName {
return fmt.Errorf("unexpected repo name; want: %s, have %s", wantName, haveName) return fmt.Errorf("unexpected repository name; want: %s, have %s", wantName, haveName)
} }
haveURL := tr.GetURL() haveURL := tr.GetURL()
if haveURL != wantURL { if haveURL != wantURL {
return fmt.Errorf("unexpected repo url; want: %s, have %s", wantURL, haveURL) return fmt.Errorf("unexpected repository url; want: %s, have %s", wantURL, haveURL)
} }
haveCredentialName := tr.GetCredentialName() haveCredentialName := tr.GetCredentialName()
...@@ -116,17 +107,17 @@ func validateRepo(tr Repo, wantName, wantURL, wantCredentialName string, wantFor ...@@ -116,17 +107,17 @@ func validateRepo(tr Repo, wantName, wantURL, wantCredentialName string, wantFor
} }
if haveCredentialName != wantCredentialName { if haveCredentialName != wantCredentialName {
return fmt.Errorf("unexpected repo credential name; want: %s, have %s", wantCredentialName, haveCredentialName) return fmt.Errorf("unexpected repository credential name; want: %s, have %s", wantCredentialName, haveCredentialName)
} }
haveFormat := tr.GetFormat() haveFormat := tr.GetFormat()
if haveFormat != wantFormat { if haveFormat != wantFormat {
return fmt.Errorf("unexpected repo format; want: %s, have %s", wantFormat, haveFormat) return fmt.Errorf("unexpected repository format; want: %s, have %s", wantFormat, haveFormat)
} }
haveType := tr.GetType() haveType := tr.GetType()
if haveType != wantType { if haveType != wantType {
return fmt.Errorf("unexpected repo type; want: %s, have %s", wantType, haveType) return fmt.Errorf("unexpected repository type; want: %s, have %s", wantType, haveType)
} }
return nil return nil
......
...@@ -29,28 +29,28 @@ import ( ...@@ -29,28 +29,28 @@ import (
"sync" "sync"
) )
// RepoProvider is a factory for ChartRepo instances. // IRepoProvider is a factory for IChartRepo instances.
type RepoProvider interface { type IRepoProvider interface {
GetRepoByURL(URL string) (ChartRepo, error) GetRepoByURL(URL string) (IChartRepo, error)
GetRepoByName(repoName string) (ChartRepo, error) GetRepoByName(repoName string) (IChartRepo, error)
GetChartByReference(reference string) (*chart.Chart, error) GetChartByReference(reference string) (*chart.Chart, error)
} }
type repoProvider struct { type repoProvider struct {
sync.RWMutex sync.RWMutex
rs Service rs IRepoService
cp CredentialProvider cp ICredentialProvider
gcsrp GCSRepoProvider gcsrp GCSRepoProvider
repos map[string]ChartRepo repos map[string]IChartRepo
} }
// NewRepoProvider creates a new repository provider. // NewRepoProvider creates a new repository provider.
func NewRepoProvider(rs Service, gcsrp GCSRepoProvider, cp CredentialProvider) RepoProvider { func NewRepoProvider(rs IRepoService, gcsrp GCSRepoProvider, cp ICredentialProvider) IRepoProvider {
return newRepoProvider(rs, gcsrp, cp) return newRepoProvider(rs, gcsrp, cp)
} }
// newRepoProvider creates a new repository provider. // newRepoProvider creates a new repository provider.
func newRepoProvider(rs Service, gcsrp GCSRepoProvider, cp CredentialProvider) *repoProvider { func newRepoProvider(rs IRepoService, gcsrp GCSRepoProvider, cp ICredentialProvider) *repoProvider {
if rs == nil { if rs == nil {
rs = NewInmemRepoService() rs = NewInmemRepoService()
} }
...@@ -63,18 +63,18 @@ func newRepoProvider(rs Service, gcsrp GCSRepoProvider, cp CredentialProvider) * ...@@ -63,18 +63,18 @@ func newRepoProvider(rs Service, gcsrp GCSRepoProvider, cp CredentialProvider) *
gcsrp = NewGCSRepoProvider(cp) gcsrp = NewGCSRepoProvider(cp)
} }
repos := make(map[string]ChartRepo) repos := make(map[string]IChartRepo)
rp := &repoProvider{rs: rs, gcsrp: gcsrp, cp: cp, repos: repos} rp := &repoProvider{rs: rs, gcsrp: gcsrp, cp: cp, repos: repos}
return rp return rp
} }
// GetRepoService returns the repository service used by this repository provider. // GetRepoService returns the repository service used by this repository provider.
func (rp *repoProvider) GetRepoService() Service { func (rp *repoProvider) GetRepoService() IRepoService {
return rp.rs return rp.rs
} }
// GetCredentialProvider returns the credential provider used by this repository provider. // GetCredentialProvider returns the credential provider used by this repository provider.
func (rp *repoProvider) GetCredentialProvider() CredentialProvider { func (rp *repoProvider) GetCredentialProvider() ICredentialProvider {
return rp.cp return rp.cp
} }
...@@ -84,7 +84,7 @@ func (rp *repoProvider) GetGCSRepoProvider() GCSRepoProvider { ...@@ -84,7 +84,7 @@ func (rp *repoProvider) GetGCSRepoProvider() GCSRepoProvider {
} }
// GetRepoByName returns the repository with the given name. // GetRepoByName returns the repository with the given name.
func (rp *repoProvider) GetRepoByName(repoName string) (ChartRepo, error) { func (rp *repoProvider) GetRepoByName(repoName string) (IChartRepo, error) {
rp.Lock() rp.Lock()
defer rp.Unlock() defer rp.Unlock()
...@@ -100,7 +100,7 @@ func (rp *repoProvider) GetRepoByName(repoName string) (ChartRepo, error) { ...@@ -100,7 +100,7 @@ func (rp *repoProvider) GetRepoByName(repoName string) (ChartRepo, error) {
return rp.createRepoByType(cr) return rp.createRepoByType(cr)
} }
func (rp *repoProvider) createRepoByType(r Repo) (ChartRepo, error) { func (rp *repoProvider) createRepoByType(r IRepo) (IChartRepo, error) {
switch r.GetType() { switch r.GetType() {
case GCSRepoType: case GCSRepoType:
cr, err := rp.gcsrp.GetGCSRepo(r) cr, err := rp.gcsrp.GetGCSRepo(r)
...@@ -114,7 +114,7 @@ func (rp *repoProvider) createRepoByType(r Repo) (ChartRepo, error) { ...@@ -114,7 +114,7 @@ func (rp *repoProvider) createRepoByType(r Repo) (ChartRepo, error) {
return nil, fmt.Errorf("unknown repository type: %s", r.GetType()) return nil, fmt.Errorf("unknown repository type: %s", r.GetType())
} }
func (rp *repoProvider) createRepo(cr ChartRepo) (ChartRepo, error) { func (rp *repoProvider) createRepo(cr IChartRepo) (IChartRepo, error) {
name := cr.GetName() name := cr.GetName()
if _, ok := rp.repos[name]; ok { if _, ok := rp.repos[name]; ok {
return nil, fmt.Errorf("respository named %s already exists", name) return nil, fmt.Errorf("respository named %s already exists", name)
...@@ -125,7 +125,7 @@ func (rp *repoProvider) createRepo(cr ChartRepo) (ChartRepo, error) { ...@@ -125,7 +125,7 @@ func (rp *repoProvider) createRepo(cr ChartRepo) (ChartRepo, error) {
} }
// GetRepoByURL returns the repository whose URL is a prefix of the given URL. // GetRepoByURL returns the repository whose URL is a prefix of the given URL.
func (rp *repoProvider) GetRepoByURL(URL string) (ChartRepo, error) { func (rp *repoProvider) GetRepoByURL(URL string) (IChartRepo, error) {
rp.Lock() rp.Lock()
defer rp.Unlock() defer rp.Unlock()
...@@ -141,8 +141,8 @@ func (rp *repoProvider) GetRepoByURL(URL string) (ChartRepo, error) { ...@@ -141,8 +141,8 @@ func (rp *repoProvider) GetRepoByURL(URL string) (ChartRepo, error) {
return rp.createRepoByType(cr) return rp.createRepoByType(cr)
} }
func (rp *repoProvider) findRepoByURL(URL string) ChartRepo { func (rp *repoProvider) findRepoByURL(URL string) IChartRepo {
var found ChartRepo var found IChartRepo
for _, r := range rp.repos { for _, r := range rp.repos {
rURL := r.GetURL() rURL := r.GetURL()
if strings.HasPrefix(URL, rURL) { if strings.HasPrefix(URL, rURL) {
...@@ -178,17 +178,17 @@ func (rp *repoProvider) GetChartByReference(reference string) (*chart.Chart, err ...@@ -178,17 +178,17 @@ func (rp *repoProvider) GetChartByReference(reference string) (*chart.Chart, err
return r.GetChart(name) return r.GetChart(name)
} }
// GCSRepoProvider is a factory for GCS Repo instances. // GCSRepoProvider is a factory for GCS IRepo instances.
type GCSRepoProvider interface { type GCSRepoProvider interface {
GetGCSRepo(r Repo) (ObjectStorageRepo, error) GetGCSRepo(r IRepo) (IStorageRepo, error)
} }
type gcsRepoProvider struct { type gcsRepoProvider struct {
cp CredentialProvider cp ICredentialProvider
} }
// NewGCSRepoProvider creates a GCSRepoProvider. // NewGCSRepoProvider creates a GCSRepoProvider.
func NewGCSRepoProvider(cp CredentialProvider) GCSRepoProvider { func NewGCSRepoProvider(cp ICredentialProvider) GCSRepoProvider {
if cp == nil { if cp == nil {
cp = NewInmemCredentialProvider() cp = NewInmemCredentialProvider()
} }
...@@ -198,7 +198,7 @@ func NewGCSRepoProvider(cp CredentialProvider) GCSRepoProvider { ...@@ -198,7 +198,7 @@ func NewGCSRepoProvider(cp CredentialProvider) GCSRepoProvider {
// GetGCSRepo returns a new Google Cloud Storage repository. If a credential is specified, it will try to // GetGCSRepo returns a new Google Cloud Storage repository. If a credential is specified, it will try to
// fetch it and use it, and if the credential isn't found, it will fall back to an unauthenticated client. // fetch it and use it, and if the credential isn't found, it will fall back to an unauthenticated client.
func (gcsrp gcsRepoProvider) GetGCSRepo(r Repo) (ObjectStorageRepo, error) { func (gcsrp gcsRepoProvider) GetGCSRepo(r IRepo) (IStorageRepo, error) {
client, err := gcsrp.createGCSClient(r.GetCredentialName()) client, err := gcsrp.createGCSClient(r.GetCredentialName())
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -50,9 +50,9 @@ func TestRepoProvider(t *testing.T) { ...@@ -50,9 +50,9 @@ func TestRepoProvider(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
castRepo, ok := haveRepo.(ObjectStorageRepo) castRepo, ok := haveRepo.(IStorageRepo)
if !ok { if !ok {
t.Fatalf("invalid repo type, want: ObjectStorageRepo, have: %T.", haveRepo) t.Fatalf("invalid repo type, want: IStorageRepo, have: %T.", haveRepo)
} }
wantBucket := GCSPublicRepoBucket wantBucket := GCSPublicRepoBucket
...@@ -112,7 +112,7 @@ func TestGetChartByReferenceWithValidReferences(t *testing.T) { ...@@ -112,7 +112,7 @@ func TestGetChartByReferenceWithValidReferences(t *testing.T) {
} }
} }
func getTestRepoProvider(t *testing.T) RepoProvider { func getTestRepoProvider(t *testing.T) IRepoProvider {
rp := newRepoProvider(nil, nil, nil) rp := newRepoProvider(nil, nil, nil)
rs := rp.GetRepoService() rs := rp.GetRepoService()
tr, err := newRepo(TestRepoName, TestRepoURL, TestRepoCredentialName, TestRepoFormat, TestRepoType) tr, err := newRepo(TestRepoName, TestRepoURL, TestRepoCredentialName, TestRepoFormat, TestRepoType)
......
...@@ -53,7 +53,7 @@ type SecretsCredentialProvider struct { ...@@ -53,7 +53,7 @@ type SecretsCredentialProvider struct {
} }
// NewSecretsCredentialProvider creates a new secrets credential provider. // NewSecretsCredentialProvider creates a new secrets credential provider.
func NewSecretsCredentialProvider() CredentialProvider { func NewSecretsCredentialProvider() ICredentialProvider {
kubernetesConfig := &util.KubernetesConfig{ kubernetesConfig := &util.KubernetesConfig{
KubePath: *kubePath, KubePath: *kubePath,
KubeService: *kubeService, KubeService: *kubeService,
...@@ -70,7 +70,7 @@ func NewSecretsCredentialProvider() CredentialProvider { ...@@ -70,7 +70,7 @@ func NewSecretsCredentialProvider() CredentialProvider {
return &SecretsCredentialProvider{util.NewKubernetesKubectl(kubernetesConfig)} return &SecretsCredentialProvider{util.NewKubernetesKubectl(kubernetesConfig)}
} }
func parseCredential(credential string) (*RepoCredential, error) { func parseCredential(credential string) (*Credential, error) {
var c common.KubernetesSecret var c common.KubernetesSecret
if err := json.Unmarshal([]byte(credential), &c); err != nil { if err := json.Unmarshal([]byte(credential), &c); err != nil {
return nil, fmt.Errorf("cannot unmarshal credential (%s): %s", credential, err) return nil, fmt.Errorf("cannot unmarshal credential (%s): %s", credential, err)
...@@ -81,8 +81,8 @@ func parseCredential(credential string) (*RepoCredential, error) { ...@@ -81,8 +81,8 @@ func parseCredential(credential string) (*RepoCredential, error) {
return nil, fmt.Errorf("cannot unmarshal credential (%s): %s", c, err) return nil, fmt.Errorf("cannot unmarshal credential (%s): %s", c, err)
} }
// And then finally unmarshal it from yaml to RepoCredential // And then finally unmarshal it from yaml to Credential
r := &RepoCredential{} r := &Credential{}
if err := yaml.Unmarshal(d, &r); err != nil { if err := yaml.Unmarshal(d, &r); err != nil {
return nil, fmt.Errorf("cannot unmarshal credential %s (%#v)", c, err) return nil, fmt.Errorf("cannot unmarshal credential %s (%#v)", c, err)
} }
...@@ -91,7 +91,7 @@ func parseCredential(credential string) (*RepoCredential, error) { ...@@ -91,7 +91,7 @@ func parseCredential(credential string) (*RepoCredential, error) {
} }
// GetCredential returns a credential by name. // GetCredential returns a credential by name.
func (scp *SecretsCredentialProvider) GetCredential(name string) (*RepoCredential, error) { func (scp *SecretsCredentialProvider) GetCredential(name string) (*Credential, error) {
o, err := scp.k.Get(name, secretType) o, err := scp.k.Get(name, secretType)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -101,7 +101,7 @@ func (scp *SecretsCredentialProvider) GetCredential(name string) (*RepoCredentia ...@@ -101,7 +101,7 @@ func (scp *SecretsCredentialProvider) GetCredential(name string) (*RepoCredentia
} }
// SetCredential sets a credential by name. // SetCredential sets a credential by name.
func (scp *SecretsCredentialProvider) SetCredential(name string, credential *RepoCredential) error { func (scp *SecretsCredentialProvider) SetCredential(name string, credential *Credential) error {
// Marshal the credential & base64 encode it. // Marshal the credential & base64 encode it.
b, err := yaml.Marshal(credential) b, err := yaml.Marshal(credential)
if err != nil { if err != nil {
......
...@@ -37,39 +37,48 @@ type APITokenCredential string ...@@ -37,39 +37,48 @@ type APITokenCredential string
// JWTTokenCredential defines a JWT token. // JWTTokenCredential defines a JWT token.
type JWTTokenCredential string type JWTTokenCredential string
// RepoCredential holds a credential used to access a repository. // Credential holds a credential used to access a repository.
type RepoCredential struct { type Credential struct {
APIToken APITokenCredential `json:"apitoken,omitempty"` APIToken APITokenCredential `json:"apitoken,omitempty"`
BasicAuth BasicAuthCredential `json:"basicauth,omitempty"` BasicAuth BasicAuthCredential `json:"basicauth,omitempty"`
ServiceAccount JWTTokenCredential `json:"serviceaccount,omitempty"` ServiceAccount JWTTokenCredential `json:"serviceaccount,omitempty"`
} }
// CredentialProvider provides credentials for chart repositories. // ICredentialProvider provides credentials for chart repositories.
type CredentialProvider interface { type ICredentialProvider interface {
// SetCredential sets the credential for a repository. // SetCredential sets the credential for a repository.
// May not be supported by some repository services. // May not be supported by some repository services.
SetCredential(name string, credential *RepoCredential) error SetCredential(name string, credential *Credential) error
// GetCredential returns the specified credential or nil if there's no credential. // GetCredential returns the specified credential or nil if there's no credential.
// Error is non-nil if fetching the credential failed. // Error is non-nil if fetching the credential failed.
GetCredential(name string) (*RepoCredential, error) GetCredential(name string) (*Credential, error)
} }
// RepoType defines the technology that implements a repository. // ERepoType defines the technology that implements a repository.
type RepoType string type ERepoType string
// RepoFormat is a semi-colon delimited string that describes the format of a repository. // ERepoFormat is a semi-colon delimited string that describes the format of a repository.
type RepoFormat string type ERepoFormat string
const ( const (
// PathRepoFormat identfies a repository where charts are organized hierarchically. // PathRepoFormat identfies a repository where charts are organized hierarchically.
PathRepoFormat = RepoFormat("path") PathRepoFormat = ERepoFormat("path")
// FlatRepoFormat identifies a repository where all charts appear at the top level. // FlatRepoFormat identifies a repository where all charts appear at the top level.
FlatRepoFormat = RepoFormat("flat") FlatRepoFormat = ERepoFormat("flat")
) )
// Repo abstracts a repository. // Repo describes a repository
type Repo interface { type Repo struct {
Name string `json:"name"` // Friendly name for this repository
URL string `json:"url"` // URL to the root of this repository
CredentialName string `json:"credentialname"` // Credential name used to access this repository
Format ERepoFormat `json:"format"` // Format of this repository
Type ERepoType `json:"type"` // Technology implementing this repository
}
// IRepo abstracts a repository.
type IRepo interface {
// GetName returns the friendly name of this repository. // GetName returns the friendly name of this repository.
GetName() string GetName() string
// GetURL returns the URL to the root of this repository. // GetURL returns the URL to the root of this repository.
...@@ -77,15 +86,15 @@ type Repo interface { ...@@ -77,15 +86,15 @@ type Repo interface {
// GetCredentialName returns the credential name used to access this repository. // GetCredentialName returns the credential name used to access this repository.
GetCredentialName() string GetCredentialName() string
// GetFormat returns the format of this repository. // GetFormat returns the format of this repository.
GetFormat() RepoFormat GetFormat() ERepoFormat
// GetType returns the technology implementing this repository. // GetType returns the technology implementing this repository.
GetType() RepoType GetType() ERepoType
} }
// ChartRepo abstracts a place that holds charts. // IChartRepo abstracts a place that holds charts.
type ChartRepo interface { type IChartRepo interface {
// A ChartRepo is a Repo // A IChartRepo is a IRepo
Repo IRepo
// ListCharts lists charts in this repository whose string values // ListCharts lists charts in this repository whose string values
// conform to the supplied regular expression, or all charts if regex is nil // conform to the supplied regular expression, or all charts if regex is nil
...@@ -95,27 +104,27 @@ type ChartRepo interface { ...@@ -95,27 +104,27 @@ type ChartRepo interface {
GetChart(name string) (*chart.Chart, error) GetChart(name string) (*chart.Chart, error)
} }
// ObjectStorageRepo abstracts a repository that resides in Object Storage, // IStorageRepo abstracts a repository that resides in Object Storage,
// such as Google Cloud Storage, AWS S3, etc. // such as Google Cloud Storage, AWS S3, etc.
type ObjectStorageRepo interface { type IStorageRepo interface {
// An ObjectStorageRepo is a ChartRepo // An IStorageRepo is a IChartRepo
ChartRepo IChartRepo
// GetBucket returns the name of the bucket that contains this repository. // GetBucket returns the name of the bucket that contains this repository.
GetBucket() string GetBucket() string
} }
// Service maintains a list of chart repositories that defines the scope of all // IRepoService maintains a list of chart repositories that defines the scope of all
// repository based operations, such as search and chart reference resolution. // repository based operations, such as search and chart reference resolution.
type Service interface { type IRepoService interface {
// List returns the list of all known chart repositories // List returns the list of all known chart repositories
List() ([]Repo, error) List() ([]IRepo, error)
// Create adds a known repository to the list // Create adds a known repository to the list
Create(repository Repo) error Create(repository IRepo) error
// Get returns the repository with the given name // Get returns the repository with the given name
Get(name string) (Repo, error) Get(name string) (IRepo, error)
// GetByURL returns the repository that backs the given URL // GetByURL returns the repository that backs the given URL
GetByURL(URL string) (Repo, error) GetByURL(URL string) (IRepo, error)
// Delete removes a known repository from the list // Delete removes a known repository from the list
Delete(name string) error Delete(name string) error
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment