Commit 17f22d77 authored by jackgr's avatar jackgr

Merge changes from #172.

parent 3cca3065
...@@ -190,7 +190,7 @@ type Registry struct { ...@@ -190,7 +190,7 @@ type Registry struct {
type RegistryType string type RegistryType string
const ( const (
Github RegistryType = "github" GithubRegistryType RegistryType = "github"
) )
// RegistryFormat defines the format of the registry // RegistryFormat defines the format of the registry
......
...@@ -82,7 +82,7 @@ var usage = func() { ...@@ -82,7 +82,7 @@ var usage = func() {
} }
func getGitRegistry() (registry.Registry, error) { func getGitRegistry() (registry.Registry, error) {
return registry.NewDefaultRegistryProvider().GetRegistry(*template_registry) return registry.NewDefaultRegistryProvider().GetRegistryByURL(*template_registry)
} }
func main() { func main() {
......
...@@ -50,6 +50,9 @@ var deployments = []Route{ ...@@ -50,6 +50,9 @@ var deployments = []Route{
{"ListTypes", "/types", "GET", listTypesHandlerFunc, ""}, {"ListTypes", "/types", "GET", listTypesHandlerFunc, ""},
{"ListTypeInstances", "/types/{type}/instances", "GET", listTypeInstancesHandlerFunc, ""}, {"ListTypeInstances", "/types/{type}/instances", "GET", listTypeInstancesHandlerFunc, ""},
{"ListRegistries", "/registries", "GET", listRegistriesHandlerFunc, ""}, {"ListRegistries", "/registries", "GET", listRegistriesHandlerFunc, ""},
{"GetRegistry", "/registries/{registry}", "GET", getRegistryHandlerFunc, ""},
{"ListCharts", "/registries/{registry}/charts", "GET", listChartsHandlerFunc, ""},
{"GetChart", "/registries/{registry}/charts/{chart}", "GET", getChartHandlerFunc, ""},
} }
var ( var (
...@@ -72,11 +75,13 @@ func init() { ...@@ -72,11 +75,13 @@ func init() {
} }
func newManager() manager.Manager { func newManager() manager.Manager {
expander := manager.NewExpander(getServiceURL(*expanderURL, *expanderName), manager.NewTypeResolver(registry.NewDefaultRegistryProvider())) provider := registry.NewDefaultRegistryProvider()
resolver := manager.NewTypeResolver(provider)
expander := manager.NewExpander(getServiceURL(*expanderURL, *expanderName), resolver)
deployer := manager.NewDeployer(getServiceURL(*deployerURL, *deployerName)) deployer := manager.NewDeployer(getServiceURL(*deployerURL, *deployerName))
r := repository.NewMapBasedRepository() r := repository.NewMapBasedRepository()
registryService := registry.NewInmemRepositoryService() service := registry.NewInmemRegistryService()
return manager.NewManager(expander, deployer, r, registryService) return manager.NewManager(expander, deployer, r, provider, service)
} }
func getServiceURL(serviceURL, serviceName string) string { func getServiceURL(serviceURL, serviceName string) string {
...@@ -342,5 +347,62 @@ func listRegistriesHandlerFunc(w http.ResponseWriter, r *http.Request) { ...@@ -342,5 +347,62 @@ func listRegistriesHandlerFunc(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
return return
} }
util.LogHandlerExitWithJSON(handler, w, registries, http.StatusOK) util.LogHandlerExitWithJSON(handler, w, registries, http.StatusOK)
} }
func getRegistryHandlerFunc(w http.ResponseWriter, r *http.Request) {
handler := "manager: get registry"
util.LogHandlerEntry(handler, r)
registryName, err := getPathVariable(w, r, "registry", handler)
if err != nil {
return
}
cr, err := backend.GetRegistry(registryName)
if err != nil {
util.LogAndReturnError(handler, http.StatusBadRequest, err, w)
return
}
util.LogHandlerExitWithJSON(handler, w, cr, http.StatusOK)
}
func listChartsHandlerFunc(w http.ResponseWriter, r *http.Request) {
handler := "manager: list charts"
util.LogHandlerEntry(handler, r)
registryName, err := getPathVariable(w, r, "registry", handler)
if err != nil {
return
}
chartNames, err := backend.ListCharts(registryName)
if err != nil {
util.LogAndReturnError(handler, http.StatusInternalServerError, err, w)
return
}
util.LogHandlerExitWithJSON(handler, w, chartNames, http.StatusOK)
}
func getChartHandlerFunc(w http.ResponseWriter, r *http.Request) {
handler := "manager: get chart"
util.LogHandlerEntry(handler, r)
registryName, err := getPathVariable(w, r, "registry", handler)
if err != nil {
return
}
chartName, err := getPathVariable(w, r, "chart", handler)
if err != nil {
return
}
c, err := backend.GetChart(registryName, chartName)
if err != nil {
util.LogAndReturnError(handler, http.StatusBadRequest, err, w)
return
}
util.LogHandlerExitWithJSON(handler, w, c, http.StatusOK)
}
...@@ -28,33 +28,48 @@ import ( ...@@ -28,33 +28,48 @@ import (
// Manager manages a persistent set of Deployments. // Manager manages a persistent set of Deployments.
type Manager interface { type Manager interface {
// Deployments
ListDeployments() ([]common.Deployment, error) ListDeployments() ([]common.Deployment, error)
GetDeployment(name string) (*common.Deployment, error) GetDeployment(name string) (*common.Deployment, error)
CreateDeployment(t *common.Template) (*common.Deployment, error) CreateDeployment(t *common.Template) (*common.Deployment, error)
DeleteDeployment(name string, forget bool) (*common.Deployment, error) DeleteDeployment(name string, forget bool) (*common.Deployment, error)
PutDeployment(name string, t *common.Template) (*common.Deployment, error) PutDeployment(name string, t *common.Template) (*common.Deployment, error)
// Manifests
ListManifests(deploymentName string) (map[string]*common.Manifest, error) ListManifests(deploymentName string) (map[string]*common.Manifest, error)
GetManifest(deploymentName string, manifest string) (*common.Manifest, error) GetManifest(deploymentName string, manifest string) (*common.Manifest, error)
Expand(t *common.Template) (*common.Manifest, error) Expand(t *common.Template) (*common.Manifest, error)
// Types
ListTypes() []string ListTypes() []string
ListInstances(typeName string) []*common.TypeInstance ListInstances(typeName string) []*common.TypeInstance
// Registry related functions
// Registries
ListRegistries() ([]*common.Registry, error) ListRegistries() ([]*common.Registry, error)
CreateRegistry(pr *common.Registry) error CreateRegistry(pr *common.Registry) error
GetRegistry(name string) (*common.Registry, error) GetRegistry(name string) (*common.Registry, error)
DeleteRegistry(name string) error DeleteRegistry(name string) error
// Charts
ListCharts(registryName string) ([]string, error)
GetChart(registryName, chartName string) (*registry.Chart, error)
} }
type manager struct { type manager struct {
expander Expander expander Expander
deployer Deployer deployer Deployer
repository repository.Repository repository repository.Repository
registryService registry.RegistryService provider registry.RegistryProvider
service registry.RegistryService
} }
// NewManager returns a new initialized Manager. // NewManager returns a new initialized Manager.
func NewManager(expander Expander, deployer Deployer, repository repository.Repository, registryService registry.RegistryService) Manager { func NewManager(expander Expander,
return &manager{expander, deployer, repository, registryService} deployer Deployer,
repository repository.Repository,
provider registry.RegistryProvider,
service registry.RegistryService) Manager {
return &manager{expander, deployer, repository, provider, service}
} }
// ListDeployments returns the list of deployments // ListDeployments returns the list of deployments
...@@ -309,20 +324,21 @@ func (m *manager) ListInstances(typeName string) []*common.TypeInstance { ...@@ -309,20 +324,21 @@ func (m *manager) ListInstances(typeName string) []*common.TypeInstance {
return m.repository.GetTypeInstances(typeName) return m.repository.GetTypeInstances(typeName)
} }
// ListRegistries returns the list of registries
func (m *manager) ListRegistries() ([]*common.Registry, error) { func (m *manager) ListRegistries() ([]*common.Registry, error) {
return m.registryService.List() return m.service.List()
} }
func (m *manager) CreateRegistry(pr *common.Registry) error { func (m *manager) CreateRegistry(pr *common.Registry) error {
return m.registryService.Create(pr) return m.service.Create(pr)
} }
func (m *manager) GetRegistry(name string) (*common.Registry, error) { func (m *manager) GetRegistry(name string) (*common.Registry, error) {
return m.registryService.Get(name) return m.service.Get(name)
} }
func (m *manager) DeleteRegistry(name string) error { func (m *manager) DeleteRegistry(name string) error {
return m.registryService.Delete(name) return m.service.Delete(name)
} }
func generateManifestName() string { func generateManifestName() string {
...@@ -346,3 +362,23 @@ func getResourceErrors(c *common.Configuration) []string { ...@@ -346,3 +362,23 @@ func getResourceErrors(c *common.Configuration) []string {
return errs return errs
} }
// ListCharts retrieves the names of the charts in a given registry.
func (m *manager) ListCharts(registryName string) ([]string, error) {
r, err := m.provider.GetRegistryByName(registryName)
if err != nil {
return nil, err
}
return r.ListCharts()
}
// GetChart retrieves a given chart in a given registry.
func (m *manager) GetChart(registryName, chartName string) (*registry.Chart, error) {
r, err := m.provider.GetRegistryByName(registryName)
if err != nil {
return nil, err
}
return r.GetChart(chartName)
}
...@@ -66,7 +66,7 @@ var deploymentList = []common.Deployment{deployment, {Name: "test2"}} ...@@ -66,7 +66,7 @@ var deploymentList = []common.Deployment{deployment, {Name: "test2"}}
var typeInstMap = map[string][]string{"test": []string{"test"}} var typeInstMap = map[string][]string{"test": []string{"test"}}
var errTest = errors.New("test") var errTest = errors.New("test error")
type expanderStub struct{} type expanderStub struct{}
...@@ -164,6 +164,7 @@ func (repository *repositoryStub) ListDeployments() ([]common.Deployment, error) ...@@ -164,6 +164,7 @@ func (repository *repositoryStub) ListDeployments() ([]common.Deployment, error)
if repository.FailListDeployments { if repository.FailListDeployments {
return deploymentList, errTest return deploymentList, errTest
} }
return deploymentList, nil return deploymentList, nil
} }
...@@ -249,11 +250,102 @@ func (r *repositoryStub) SetTypeInstances(d string, is map[string][]*common.Type ...@@ -249,11 +250,102 @@ func (r *repositoryStub) SetTypeInstances(d string, is map[string][]*common.Type
} }
} }
type registryStub struct {
FailListCharts bool
FailGetChart bool
ListChartsCalled bool
GetChartCalled bool
}
func newRegistryStub() *registryStub {
ret := &registryStub{}
return ret
}
func (r *registryStub) reset() {
r.FailListCharts = false
r.FailGetChart = false
r.ListChartsCalled = false
r.GetChartCalled = false
}
var testRegistryName = "TestRegistry"
var testRegistryURL = "https://github.com/helm/charts"
var testChartName = "TestChart"
var testChart = registry.Chart{
Name: testChartName,
}
var testChartList = []string{testChartName, "TestChart2"}
func (r *registryStub) GetRegistryName() string {
return testRegistryName
}
func (r *registryStub) GetRegistryType() common.RegistryType {
return common.GithubRegistryType
}
func (r *registryStub) GetRegistryURL() string {
return testRegistryURL
}
func (r *registryStub) ListCharts() ([]string, error) {
if r.FailListCharts {
return nil, errTest
}
return testChartList, nil
}
func (r *registryStub) GetChart(chartName string) (*registry.Chart, error) {
if !r.FailGetChart {
if chartName == testChartName {
return &testChart, nil
}
}
return nil, errTest
}
// Deprecated: Use ListCharts, instead.
func (r *registryStub) List() ([]registry.Type, error) {
return []registry.Type{}, nil
}
// Deprecated: Use GetChart, instead.
func (r *registryStub) GetURLs(t registry.Type) ([]string, error) {
return []string{}, nil
}
type registryProviderStub struct {
FailGetGithubRegistry bool
FailGetGithubPackageRegistry bool
}
var testRegistryOwner = "TestOwner"
var testRegistryRepository = "TestRepository"
func newRegistryProviderStub() *registryProviderStub {
ret := &registryProviderStub{}
return ret
}
func (rp *registryProviderStub) GetRegistryByURL(URL string) (registry.Registry, error) {
return newRegistryStub(), nil
}
func (rp *registryProviderStub) GetRegistryByName(registryName string) (registry.Registry, error) {
return newRegistryStub(), nil
}
var testExpander = &expanderStub{} var testExpander = &expanderStub{}
var testRepository = newRepositoryStub() var testRepository = newRepositoryStub()
var testDeployer = newDeployerStub() var testDeployer = newDeployerStub()
var testRegistryService = registry.NewInmemRepositoryService() var testRegistryService = registry.NewInmemRegistryService()
var testManager = NewManager(testExpander, testDeployer, testRepository, testRegistryService) var testProvider = newRegistryProviderStub()
var testManager = NewManager(testExpander, testDeployer, testRepository, testProvider, testRegistryService)
func TestListDeployments(t *testing.T) { func TestListDeployments(t *testing.T) {
testRepository.reset() testRepository.reset()
......
...@@ -244,7 +244,7 @@ func (tr *typeResolver) ShortTypeToDownloadURLs(template string) ([]string, erro ...@@ -244,7 +244,7 @@ func (tr *typeResolver) ShortTypeToDownloadURLs(template string) ([]string, erro
if len(m) != 6 { if len(m) != 6 {
return []string{}, fmt.Errorf("Failed to parse short github url: %s", template) return []string{}, fmt.Errorf("Failed to parse short github url: %s", template)
} }
r, err := tr.rp.GetRegistry(template) r, err := tr.rp.GetRegistryByURL(template)
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }
...@@ -262,7 +262,7 @@ func (tr *typeResolver) ShortTypeToPackageDownloadURLs(template string) ([]strin ...@@ -262,7 +262,7 @@ func (tr *typeResolver) ShortTypeToPackageDownloadURLs(template string) ([]strin
if len(m) != 4 { if len(m) != 4 {
return []string{}, fmt.Errorf("Failed to parse short github url: %s", template) return []string{}, fmt.Errorf("Failed to parse short github url: %s", template)
} }
r, err := tr.rp.GetRegistry(template) r, err := tr.rp.GetRegistryByURL(template)
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }
......
...@@ -74,26 +74,58 @@ func newTestRegistryProvider(URLPrefix string, tests map[registry.Type]urlAndErr ...@@ -74,26 +74,58 @@ func newTestRegistryProvider(URLPrefix string, tests map[registry.Type]urlAndErr
return &testRegistryProvider{URLPrefix, r} return &testRegistryProvider{URLPrefix, r}
} }
// Deprecated: Use GetRegistryByURL, instead.
func (trp *testRegistryProvider) GetRegistry(URL string) (registry.Registry, error) { func (trp *testRegistryProvider) GetRegistry(URL string) (registry.Registry, error) {
return trp.GetRegistryByURL(URL)
}
func (trp *testRegistryProvider) GetRegistryByURL(URL string) (registry.Registry, error) {
for key, r := range trp.r { for key, r := range trp.r {
if strings.HasPrefix(URL, key) { if strings.HasPrefix(URL, key) {
return r, nil return r, nil
} }
} }
return nil, fmt.Errorf("No registry found for %s", URL) return nil, fmt.Errorf("No registry found for %s", URL)
} }
func (trp *testRegistryProvider) GetRegistryByName(registryName string) (registry.Registry, error) {
return newRegistryStub(), nil
}
type testGithubRegistry struct { type testGithubRegistry struct {
responses map[registry.Type]urlAndError responses map[registry.Type]urlAndError
count int count int
} }
func (r *testGithubRegistry) GetRegistryName() string {
return ""
}
func (r *testGithubRegistry) GetRegistryType() common.RegistryType {
return common.GithubRegistryType
}
func (r *testGithubRegistry) GetRegistryURL() string {
return ""
}
func (r *testGithubRegistry) ListCharts() ([]string, error) {
return []string{}, fmt.Errorf("ListCharts should not be called in the test")
}
func (r *testGithubRegistry) GetChart(chartName string) (*registry.Chart, error) {
return nil, fmt.Errorf("GetChart should not be called in the test")
}
// Deprecated: Use GetChart, instead.
func (tgr *testGithubRegistry) GetURLs(t registry.Type) ([]string, error) { func (tgr *testGithubRegistry) GetURLs(t registry.Type) ([]string, error) {
tgr.count = tgr.count + 1 tgr.count = tgr.count + 1
ret := tgr.responses[t] ret := tgr.responses[t]
return []string{ret.u}, ret.e return []string{ret.u}, ret.e
} }
// Deprecated: Use ListCharts, instead.
func (tgr *testGithubRegistry) List() ([]registry.Type, error) { func (tgr *testGithubRegistry) List() ([]registry.Type, error) {
return []registry.Type{}, fmt.Errorf("List should not be called in the test") return []registry.Type{}, fmt.Errorf("List should not be called in the test")
} }
......
...@@ -17,10 +17,11 @@ limitations under the License. ...@@ -17,10 +17,11 @@ limitations under the License.
package registry package registry
import ( import (
"github.com/google/go-github/github"
"github.com/kubernetes/deployment-manager/common"
"log" "log"
"strings" "strings"
"github.com/google/go-github/github"
) )
// GithubPackageRegistry implements the Registry interface that talks to github and // GithubPackageRegistry implements the Registry interface that talks to github and
...@@ -47,6 +48,37 @@ func NewGithubPackageRegistry(owner, repository string, client *github.Client) * ...@@ -47,6 +48,37 @@ func NewGithubPackageRegistry(owner, repository string, client *github.Client) *
} }
} }
// GetRegistryName returns the name of this registry
func (g *GithubPackageRegistry) GetRegistryName() string {
// TODO(jackgr): implement this method
return ""
}
// GetRegistryType returns the type of this registry.
func (g *GithubPackageRegistry) GetRegistryType() common.RegistryType {
// TODO(jackgr): implement this method
return common.GithubRegistryType
}
// GetRegistryURL returns the URL for this registry.
func (g *GithubPackageRegistry) GetRegistryURL() string {
// TODO(jackgr): implement this method
return ""
}
// ListCharts lists the versioned chart names in this registry.
func (g *GithubPackageRegistry) ListCharts() ([]string, error) {
// TODO(jackgr): implement this method
return []string{}, nil
}
// GetChart fetches the contents of a given chart.
func (g *GithubPackageRegistry) GetChart(chartName string) (*Chart, error) {
// TODO(jackgr): implement this method
return nil, nil
}
// Deprecated: Use ListCharts, instead.
// List the types from the Registry. // List the types from the Registry.
func (g *GithubPackageRegistry) List() ([]Type, error) { func (g *GithubPackageRegistry) List() ([]Type, error) {
// Just list all the types at the top level. // Just list all the types at the top level.
...@@ -74,6 +106,7 @@ func (g *GithubPackageRegistry) List() ([]Type, error) { ...@@ -74,6 +106,7 @@ func (g *GithubPackageRegistry) List() ([]Type, error) {
return retTypes, nil return retTypes, nil
} }
// Deprecated: Use GetChart, instead.
// GetURLs fetches the download URLs for a given Type. // GetURLs fetches the download URLs for a given Type.
func (g *GithubPackageRegistry) GetURLs(t Type) ([]string, error) { func (g *GithubPackageRegistry) GetURLs(t Type) ([]string, error) {
path, err := g.MakeRepositoryPath(t) path, err := g.MakeRepositoryPath(t)
......
...@@ -18,6 +18,7 @@ package registry ...@@ -18,6 +18,7 @@ package registry
import ( import (
"github.com/google/go-github/github" "github.com/google/go-github/github"
"github.com/kubernetes/deployment-manager/common"
"fmt" "fmt"
"log" "log"
...@@ -64,6 +65,58 @@ func NewGithubRegistry(owner, repository, path string, client *github.Client) *G ...@@ -64,6 +65,58 @@ func NewGithubRegistry(owner, repository, path string, client *github.Client) *G
} }
} }
// GetRegistryName returns the name of this registry
func (g *GithubRegistry) GetRegistryName() string {
// TODO(jackgr): implement this method
return ""
}
// GetRegistryType returns the type of this registry.
func (g *GithubRegistry) GetRegistryType() common.RegistryType {
// TODO(jackgr): implement this method
return common.GithubRegistryType
}
// GetRegistryURL returns the URL for this registry.
func (g *GithubRegistry) GetRegistryURL() string {
// TODO(jackgr): implement this method
return ""
}
// ListCharts lists the versioned chart names in this registry.
func (g *GithubRegistry) ListCharts() ([]string, error) {
var result []string
names, err := g.getDirs("")
if err != nil {
log.Printf("Failed to fetch chart names from registry: %s/%s/%s", g.owner, g.repository, g.path)
return nil, err
}
// Fetch the chart names
for _, name := range names {
// Then fetch the versions for each chart name
versions, err := g.getDirs("/" + name)
if err != nil {
log.Printf("Failed to fetch versions for chart name: %s/%s/%s/%s",
g.owner, g.repository, g.path, name)
return nil, err
}
for _, version := range versions {
result = append(result, fmt.Sprintf("%s#%s", name, version))
}
}
return result, nil
}
// GetChart fetches the contents of a given chart.
func (g *GithubRegistry) GetChart(chartName string) (*Chart, error) {
// TODO(jackgr): implement this method
return nil, nil
}
// Deprecated: Use ListCharts, instead.
// List the types from the Registry. // List the types from the Registry.
func (g *GithubRegistry) List() ([]Type, error) { func (g *GithubRegistry) List() ([]Type, error) {
// First list all the collections at the top level. // First list all the collections at the top level.
...@@ -98,6 +151,7 @@ func (g *GithubRegistry) List() ([]Type, error) { ...@@ -98,6 +151,7 @@ func (g *GithubRegistry) List() ([]Type, error) {
return retTypes, nil return retTypes, nil
} }
// Deprecated: Use GetChart, instead.
// GetURL fetches the download URL for a given Type and checks for existence of a schema file. // GetURL fetches the download URL for a given Type and checks for existence of a schema file.
func (g *GithubRegistry) GetURLs(t Type) ([]string, error) { func (g *GithubRegistry) GetURLs(t Type) ([]string, error) {
path, err := g.MakeRepositoryPath(t) path, err := g.MakeRepositoryPath(t)
......
...@@ -23,53 +23,53 @@ import ( ...@@ -23,53 +23,53 @@ import (
"github.com/kubernetes/deployment-manager/common" "github.com/kubernetes/deployment-manager/common"
) )
type inmemRepositoryService struct { type inmemRegistryService struct {
repositories map[string]*common.Registry registries map[string]*common.Registry
} }
func NewInmemRepositoryService() RegistryService { func NewInmemRegistryService() RegistryService {
rs := &inmemRepositoryService{ rs := &inmemRegistryService{
repositories: make(map[string]*common.Registry), registries: make(map[string]*common.Registry),
} }
rs.Create(&common.Registry{ rs.Create(&common.Registry{
Name: "charts", Name: "charts",
Type: common.Github, Type: common.GithubRegistryType,
URL: "github.com/helm/charts", URL: "github.com/helm/charts",
Format: common.UnversionedRegistry, Format: common.UnversionedRegistry,
}) })
rs.Create(&common.Registry{ rs.Create(&common.Registry{
Name: "application-dm-templates", Name: "application-dm-templates",
Type: common.Github, Type: common.GithubRegistryType,
URL: "github.com/kubernetes/application-dm-templates", URL: "github.com/kubernetes/application-dm-templates",
Format: common.VersionedRegistry, Format: common.VersionedRegistry,
}) })
return rs return rs
} }
func (rs *inmemRepositoryService) List() ([]*common.Registry, error) { func (rs *inmemRegistryService) List() ([]*common.Registry, error) {
ret := []*common.Registry{} ret := []*common.Registry{}
for _, r := range rs.repositories { for _, r := range rs.registries {
ret = append(ret, r) ret = append(ret, r)
} }
return ret, nil return ret, nil
} }
func (rs *inmemRepositoryService) Create(repository *common.Registry) error { func (rs *inmemRegistryService) Create(registry *common.Registry) error {
rs.repositories[repository.URL] = repository rs.registries[registry.URL] = registry
return nil return nil
} }
func (rs *inmemRepositoryService) Get(name string) (*common.Registry, error) { func (rs *inmemRegistryService) Get(name string) (*common.Registry, error) {
return &common.Registry{}, nil return &common.Registry{}, nil
} }
func (rs *inmemRepositoryService) Delete(name string) error { func (rs *inmemRegistryService) Delete(name string) error {
return nil return nil
} }
// GetByURL returns a registry that handles the types for a given URL. // GetByURL returns a registry that handles the types for a given URL.
func (rs *inmemRepositoryService) GetByURL(URL string) (*common.Registry, error) { func (rs *inmemRegistryService) GetByURL(URL string) (*common.Registry, error) {
for _, r := range rs.repositories { for _, r := range rs.registries {
if strings.HasPrefix(URL, r.URL) { if strings.HasPrefix(URL, r.URL) {
return r, nil return r, nil
} }
......
...@@ -20,13 +20,37 @@ import ( ...@@ -20,13 +20,37 @@ import (
"strings" "strings"
"github.com/kubernetes/deployment-manager/common" "github.com/kubernetes/deployment-manager/common"
"net/url"
) )
// 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 {
// GetRegistryName returns the name of this registry
GetRegistryName() string
// GetRegistryType returns the type of this registry.
GetRegistryType() common.RegistryType
// GetRegistryURL returns the URL for this registry.
GetRegistryURL() string
// ListCharts lists the versioned chart names in this registry.
ListCharts() ([]string, error)
// GetChart fetches the contents of a given chart.
GetChart(chartName string) (*Chart, error)
// Deprecated: Use ListCharts, instead.
List() ([]Type, error)
// Deprecated: Use GetChart, instead.
GetURLs(t Type) ([]string, error)
}
type RegistryService interface { type RegistryService interface {
// List all the registries // List all the registries
List() ([]*common.Registry, error) List() ([]*common.Registry, error)
// Create a new registry // Create a new registry
Create(repository *common.Registry) error Create(registry *common.Registry) error
// Get a registry // Get a registry
Get(name string) (*common.Registry, error) Get(name string) (*common.Registry, error)
// Delete a registry // Delete a registry
...@@ -35,13 +59,7 @@ type RegistryService interface { ...@@ -35,13 +59,7 @@ type RegistryService interface {
GetByURL(URL string) (*common.Registry, error) GetByURL(URL string) (*common.Registry, error)
} }
// Registry abstracts a registry that holds templates, which can be // Deprecated: Use Chart, instead
// used in a Deployment Manager configurations. There can be multiple
// implementations of a registry. Currently we support Deployment Manager
// github.com/kubernetes/application-dm-templates
// and helm packages
// github.com/helm/charts
//
type Type struct { type Type struct {
Collection string Collection string
Name string Name string
...@@ -68,10 +86,12 @@ func ParseType(name string) *Type { ...@@ -68,10 +86,12 @@ func ParseType(name string) *Type {
return tt return tt
} }
// Registry abstracts type interactions. type Chart struct {
type Registry interface { Name string
// List all the templates at the given path Version SemVer
List() ([]Type, error) RegistryURL string
// Get the download URL(s) for a given type DownloadURLs []url.URL
GetURLs(t Type) ([]string, error)
// TODO(jackgr): Should the metadata be strongly typed?
Metadata map[string]interface{}
} }
...@@ -18,38 +18,97 @@ package registry ...@@ -18,38 +18,97 @@ package registry
import ( import (
"fmt" "fmt"
"strings"
"sync"
"github.com/google/go-github/github" "github.com/google/go-github/github"
"github.com/kubernetes/deployment-manager/common" "github.com/kubernetes/deployment-manager/common"
) )
// RegistryProvider returns factories for creating registries for a given RegistryType. // RegistryProvider returns factories for creating registry clients.
type RegistryProvider interface { type RegistryProvider interface {
GetRegistry(prefix string) (Registry, error) GetRegistryByURL(URL string) (Registry, error)
GetRegistryByName(registryName string) (Registry, error)
} }
func NewDefaultRegistryProvider() RegistryProvider { func NewDefaultRegistryProvider() RegistryProvider {
rs := NewInmemRepositoryService() registries := make(map[string]Registry)
return &DefaultRegistryProvider{rs: rs} rs := NewInmemRegistryService()
return &DefaultRegistryProvider{registries: registries, rs: rs}
} }
type DefaultRegistryProvider struct { type DefaultRegistryProvider struct {
rs RegistryService sync.RWMutex
registries map[string]Registry
rs RegistryService
} }
func (drp *DefaultRegistryProvider) GetRegistry(URL string) (Registry, error) { func (drp *DefaultRegistryProvider) GetRegistryByURL(URL string) (Registry, error) {
r, err := drp.rs.GetByURL(URL) drp.RLock()
if err != nil { defer drp.RUnlock()
return nil, err
ghr := drp.findRegistryByURL(URL)
if ghr == nil {
cr, err := drp.rs.GetByURL(URL)
if err != nil {
return nil, err
}
ghr, err := drp.getGithubRegistry(cr)
if err != nil {
return nil, err
}
drp.registries[ghr.GetRegistryName()] = ghr
} }
if r.Type == common.Github {
if r.Format == common.UnversionedRegistry { return ghr, nil
return NewGithubPackageRegistry("helm", "charts", github.NewClient(nil)), nil }
func (drp *DefaultRegistryProvider) findRegistryByURL(URL string) Registry {
for _, ghr := range drp.registries {
if strings.HasPrefix(URL, ghr.GetRegistryURL()) {
return ghr
} }
if r.Format == common.VersionedRegistry { }
return nil
}
func (drp *DefaultRegistryProvider) GetRegistryByName(registryName string) (Registry, error) {
drp.RLock()
defer drp.RUnlock()
ghr, ok := drp.registries[registryName]
if !ok {
cr, err := drp.rs.Get(registryName)
if err != nil {
return nil, err
}
ghr, err := drp.getGithubRegistry(cr)
if err != nil {
return nil, err
}
drp.registries[ghr.GetRegistryName()] = ghr
}
return ghr, nil
}
func (drp *DefaultRegistryProvider) getGithubRegistry(cr *common.Registry) (Registry, error) {
// TODO(jackgr): Take owner and repository from cr instead of hard wiring
if cr.Type == common.GithubRegistryType {
switch cr.Format {
case common.UnversionedRegistry:
return NewGithubPackageRegistry("helm", "charts", github.NewClient(nil)), nil
case common.VersionedRegistry:
return NewGithubRegistry("kubernetes", "application-dm-templates", "", github.NewClient(nil)), nil return NewGithubRegistry("kubernetes", "application-dm-templates", "", github.NewClient(nil)), nil
default:
return nil, fmt.Errorf("unknown registry format: %s", cr.Format)
} }
} }
return nil, fmt.Errorf("cannot find registry backing url %s", URL)
return nil, fmt.Errorf("unknown registry type: %s", cr.Type)
} }
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package registry
import (
"fmt"
"strconv"
"strings"
)
type SemVer struct {
Major uint
Minor uint
Patch uint
}
func NewSemVer(version string) (*SemVer, error) {
result := &SemVer{}
parts := strings.SplitN(version, ".", 3)
if len(parts) > 3 {
return nil, fmt.Errorf("invalid semantic version: %s", version)
}
major, err := strconv.ParseUint(parts[0], 10, 0)
if err != nil {
return nil, fmt.Errorf("invalid semantic version: %s", version)
}
result.Major = uint(major)
if len(parts) < 3 {
if len(parts) < 2 {
if len(parts) < 1 {
return nil, fmt.Errorf("invalid semantic version: %s", version)
}
} else {
minor, err := strconv.ParseUint(parts[1], 10, 0)
if err != nil {
return nil, fmt.Errorf("invalid semantic version: %s", version)
}
result.Minor = uint(minor)
}
} else {
patch, err := strconv.ParseUint(parts[2], 10, 0)
if err != nil {
return nil, fmt.Errorf("invalid semantic version: %s", version)
}
result.Patch = uint(patch)
}
return result, nil
}
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
}
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